blob: acd570d3154534aae83c6bdd3a4c3ff44f99bc8e [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) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100208char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200210/* List head of all known configuration keywords */
211static struct cfg_kw_list cfg_keywords = {
212 .list = LIST_HEAD_INIT(cfg_keywords.list)
213};
214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215/*
216 * converts <str> to a list of listeners which are dynamically allocated.
217 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
218 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
219 * - <port> is a numerical port from 1 to 65535 ;
220 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
221 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
223 * not NULL, it must be a valid pointer to either NULL or a freeable area that
224 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200226int 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 +0200227{
228 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 int port, end;
231
232 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200233
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100235 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100236 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
238 str = next;
239 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100240 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 *next++ = 0;
242 }
243
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200245 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200246 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (!ss2)
248 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100250 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100251 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200252 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100256 if (!port || !end) {
257 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
258 goto fail;
259 }
260
Emeric Bruned760922010-10-22 17:59:25 +0200261 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
265
266 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200267 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200268 goto fail;
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 else if (ss2->ss_family == AF_UNSPEC) {
272 socklen_t addr_len;
273
274 /* We want to attach to an already bound fd whose number
275 * is in the addr part of ss2 when cast to sockaddr_in.
276 * Note that by definition there is a single listener.
277 * We still have to determine the address family to
278 * register the correct protocol.
279 */
280 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
281 addr_len = sizeof(*ss2);
282 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
283 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
284 goto fail;
285 }
286
287 port = end = get_host_port(ss2);
288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100290 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200291 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100292
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200294 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100295 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200296 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
297 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
298 l->frontend = curproxy;
299 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300
Willy Tarreau40aa0702013-03-10 23:51:38 +0100301 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200302 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200303 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100304 l->state = LI_INIT;
305
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100306 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200307 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100308 tcpv4_add_listener(l);
309 }
Emeric Bruned760922010-10-22 17:59:25 +0200310 else if (ss.ss_family == AF_INET6) {
311 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
312 tcpv6_add_listener(l);
313 }
314 else {
Emeric Bruned760922010-10-22 17:59:25 +0200315 uxst_add_listener(l);
316 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200318 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100319 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 } /* end for(port) */
321 } /* end while(next) */
322 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200323 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324 fail:
325 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200326 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327}
328
William Lallemand6e62fb62015-04-28 16:55:23 +0200329/*
330 * Report a fatal Alert when there is too much arguments
331 * The index is the current keyword in args
332 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
333 * Fill err_code with an ERR_ALERT and an ERR_FATAL
334 */
335int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
336{
337 char *kw = NULL;
338 int i;
339
340 if (!*args[index + maxarg + 1])
341 return 0;
342
343 memprintf(&kw, "%s", args[0]);
344 for (i = 1; i <= index; i++) {
345 memprintf(&kw, "%s %s", kw, args[i]);
346 }
347
348 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
349 free(kw);
350 *err_code |= ERR_ALERT | ERR_FATAL;
351 return 1;
352}
353
354/*
355 * same as alertif_too_many_args_idx with a 0 index
356 */
357int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
358{
359 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
360}
361
Willy Tarreau620408f2016-10-21 16:37:51 +0200362/* Report a warning if a rule is placed after a 'tcp-request session' rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
365int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
366{
367 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200375/* Report a warning if a rule is placed after a 'tcp-request content' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
378int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
379{
380 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreau61d18892009-03-31 10:49:21 +0200388/* Report a warning if a rule is placed after a 'block' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200393 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau5002f572014-04-23 01:32:02 +0200401/* Report a warning if a rule is placed after an 'http_request' rule.
402 * Return 1 if the warning has been emitted, otherwise 0.
403 */
404int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
405{
406 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
407 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
408 file, line, arg);
409 return 1;
410 }
411 return 0;
412}
413
Willy Tarreau61d18892009-03-31 10:49:21 +0200414/* Report a warning if a rule is placed after a reqrewrite rule.
415 * Return 1 if the warning has been emitted, otherwise 0.
416 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100417int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200418{
419 if (proxy->req_exp) {
420 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
421 file, line, arg);
422 return 1;
423 }
424 return 0;
425}
426
427/* Report a warning if a rule is placed after a reqadd rule.
428 * Return 1 if the warning has been emitted, otherwise 0.
429 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100430int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200431{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100432 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200433 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
434 file, line, arg);
435 return 1;
436 }
437 return 0;
438}
439
440/* Report a warning if a rule is placed after a redirect rule.
441 * Return 1 if the warning has been emitted, otherwise 0.
442 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100443int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200444{
445 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
446 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
447 file, line, arg);
448 return 1;
449 }
450 return 0;
451}
452
453/* Report a warning if a rule is placed after a 'use_backend' rule.
454 * Return 1 if the warning has been emitted, otherwise 0.
455 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100456int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200457{
458 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
459 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
460 file, line, arg);
461 return 1;
462 }
463 return 0;
464}
465
Willy Tarreauee445d92014-04-23 01:39:04 +0200466/* Report a warning if a rule is placed after a 'use-server' rule.
467 * Return 1 if the warning has been emitted, otherwise 0.
468 */
469int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
470{
471 if (!LIST_ISEMPTY(&proxy->server_rules)) {
472 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
473 file, line, arg);
474 return 1;
475 }
476 return 0;
477}
478
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200479/* report a warning if a "tcp request connection" rule is dangerously placed */
480int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
481{
Willy Tarreau620408f2016-10-21 16:37:51 +0200482 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
483 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
484 warnif_rule_after_block(proxy, file, line, arg) ||
485 warnif_rule_after_http_req(proxy, file, line, arg) ||
486 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
487 warnif_rule_after_reqadd(proxy, file, line, arg) ||
488 warnif_rule_after_redirect(proxy, file, line, arg) ||
489 warnif_rule_after_use_backend(proxy, file, line, arg) ||
490 warnif_rule_after_use_server(proxy, file, line, arg);
491}
492
493int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
494{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200495 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
496 warnif_rule_after_block(proxy, file, line, arg) ||
497 warnif_rule_after_http_req(proxy, file, line, arg) ||
498 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
499 warnif_rule_after_reqadd(proxy, file, line, arg) ||
500 warnif_rule_after_redirect(proxy, file, line, arg) ||
501 warnif_rule_after_use_backend(proxy, file, line, arg) ||
502 warnif_rule_after_use_server(proxy, file, line, arg);
503}
504
505/* report a warning if a "tcp request content" rule is dangerously placed */
506int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
507{
508 return warnif_rule_after_block(proxy, file, line, arg) ||
509 warnif_rule_after_http_req(proxy, file, line, arg) ||
510 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
511 warnif_rule_after_reqadd(proxy, file, line, arg) ||
512 warnif_rule_after_redirect(proxy, file, line, arg) ||
513 warnif_rule_after_use_backend(proxy, file, line, arg) ||
514 warnif_rule_after_use_server(proxy, file, line, arg);
515}
516
Willy Tarreau61d18892009-03-31 10:49:21 +0200517/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100518int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200519{
Willy Tarreau5002f572014-04-23 01:32:02 +0200520 return warnif_rule_after_http_req(proxy, file, line, arg) ||
521 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
522 warnif_rule_after_reqadd(proxy, file, line, arg) ||
523 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200526}
527
528/* report a warning if an http-request rule is dangerously placed */
529int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
530{
Willy Tarreau61d18892009-03-31 10:49:21 +0200531 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
532 warnif_rule_after_reqadd(proxy, file, line, arg) ||
533 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200534 warnif_rule_after_use_backend(proxy, file, line, arg) ||
535 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200536}
537
538/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100539int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200540{
541 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
542 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200543 warnif_rule_after_use_backend(proxy, file, line, arg) ||
544 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
547/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100548int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
550 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200551 warnif_rule_after_use_backend(proxy, file, line, arg) ||
552 warnif_rule_after_use_server(proxy, file, line, arg);
553}
554
555/* report a warning if a redirect rule is dangerously placed */
556int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
557{
558 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
559 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200560}
561
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562/* Report it if a request ACL condition uses some keywords that are incompatible
563 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
564 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
565 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100566 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100568{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100569 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200570 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100571
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100572 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100573 return 0;
574
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 acl = acl_cond_conflicts(cond, where);
576 if (acl) {
577 if (acl->name && *acl->name)
578 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
579 file, line, acl->name, sample_ckp_names(where));
580 else
581 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 +0200582 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100583 return ERR_WARN;
584 }
585 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100586 return 0;
587
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100588 if (acl->name && *acl->name)
589 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200590 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100591 else
592 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200593 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100594 return ERR_WARN;
595}
596
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 * parse a line in a <global> section. Returns the error code, 0 if OK, or
599 * any combination of :
600 * - ERR_ABORT: must abort ASAP
601 * - ERR_FATAL: we can continue parsing but not start the service
602 * - ERR_WARN: a warning has been emitted
603 * - ERR_ALERT: an alert has been emitted
604 * Only the two first ones can stop processing, the two others are just
605 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200607int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608{
Willy Tarreau058e9072009-07-20 09:30:05 +0200609 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200610 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611
612 if (!strcmp(args[0], "global")) { /* new section */
613 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200614 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200617 else if (!strcmp(args[0], "ca-base")) {
618#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200619 if(alertif_too_many_args(1, file, linenum, args, &err_code))
620 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200621 if (global.ca_base != NULL) {
622 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
623 err_code |= ERR_ALERT;
624 goto out;
625 }
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.ca_base = strdup(args[1]);
632#else
633 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
636#endif
637 }
638 else if (!strcmp(args[0], "crt-base")) {
639#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200640 if (alertif_too_many_args(1, file, linenum, args, &err_code))
641 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200642 if (global.crt_base != NULL) {
643 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT;
645 goto out;
646 }
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.crt_base = strdup(args[1]);
653#else
654 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657#endif
658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200660 if (alertif_too_many_args(0, file, linenum, args, &err_code))
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 global.mode |= MODE_DAEMON;
663 }
664 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200665 if (alertif_too_many_args(0, file, linenum, args, &err_code))
666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 global.mode |= MODE_DEBUG;
668 }
669 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200670 if (alertif_too_many_args(0, file, linenum, args, &err_code))
671 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100672 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200674 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200675 if (alertif_too_many_args(0, file, linenum, args, &err_code))
676 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100677 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200680 if (alertif_too_many_args(0, file, linenum, args, &err_code))
681 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100682 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100684 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200685 if (alertif_too_many_args(0, file, linenum, args, &err_code))
686 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100687 global.tune.options &= ~GTUNE_USE_SPLICE;
688 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200689 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200690 if (alertif_too_many_args(0, file, linenum, args, &err_code))
691 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200692 global.tune.options &= ~GTUNE_USE_GAI;
693 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000694 else if (!strcmp(args[0], "noreuseport")) {
695 if (alertif_too_many_args(0, file, linenum, args, &err_code))
696 goto out;
697 global.tune.options &= ~GTUNE_USE_REUSEPORT;
698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200700 if (alertif_too_many_args(0, file, linenum, args, &err_code))
701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 global.mode |= MODE_QUIET;
703 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200704 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200705 if (alertif_too_many_args(1, file, linenum, args, &err_code))
706 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200707 if (global.tune.maxpollevents != 0) {
708 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
710 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200711 }
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200716 }
717 global.tune.maxpollevents = atol(args[1]);
718 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100719 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200720 if (alertif_too_many_args(1, file, linenum, args, &err_code))
721 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100722 if (global.tune.maxaccept != 0) {
723 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT;
725 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100726 }
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100731 }
732 global.tune.maxaccept = atol(args[1]);
733 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200734 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
736 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.tune.chksize = atol(args[1]);
743 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100744 else if (!strcmp(args[0], "tune.recv_enough")) {
745 if (alertif_too_many_args(1, file, linenum, args, &err_code))
746 goto out;
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 global.tune.recv_enough = atol(args[1]);
753 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200754#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200755 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200756 if (alertif_too_many_args(0, file, linenum, args, &err_code))
757 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200758 global.tune.sslprivatecache = 1;
759 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100760 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.tune.sslcachesize = atol(args[1]);
769 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100770 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
771 unsigned int ssllifetime;
772 const char *res;
773
William Lallemand1a748ae2015-05-19 16:37:23 +0200774 if (alertif_too_many_args(1, file, linenum, args, &err_code))
775 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781
782 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
783 if (res) {
784 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
785 file, linenum, *res, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789
790 global.tune.ssllifetime = ssllifetime;
791 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100792 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.ssl_max_record = atol(args[1]);
801 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200802#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200803 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
805 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.tune.ssl_default_dh_param = atol(args[1]);
812 if (global.tune.ssl_default_dh_param < 1024) {
813 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200818#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200819 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
821 goto out;
822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
826 }
827 global.tune.ssl_ctx_cache = atoi(args[1]);
828 if (global.tune.ssl_ctx_cache < 0) {
829 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
830 file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200835#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100836 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
843 }
844 global.tune.buf_limit = atol(args[1]);
845 if (global.tune.buf_limit) {
846 if (global.tune.buf_limit < 3)
847 global.tune.buf_limit = 3;
848 if (global.tune.buf_limit <= global.tune.reserved_bufs)
849 global.tune.buf_limit = global.tune.reserved_bufs + 1;
850 }
851 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100852 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200853 if (alertif_too_many_args(1, file, linenum, args, &err_code))
854 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100855 if (*(args[1]) == 0) {
856 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860 global.tune.reserved_bufs = atol(args[1]);
861 if (global.tune.reserved_bufs < 2)
862 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100863 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
864 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100865 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200866 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200875 if (global.tune.bufsize <= 0) {
876 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100880 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100881 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200882 }
883 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200884 if (alertif_too_many_args(1, file, linenum, args, &err_code))
885 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200886 if (*(args[1]) == 0) {
887 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200892 if (global.tune.maxrewrite < 0) {
893 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200897 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100898 else if (!strcmp(args[0], "tune.idletimer")) {
899 unsigned int idle;
900 const char *res;
901
William Lallemand1a748ae2015-05-19 16:37:23 +0200902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909
910 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
911 if (res) {
912 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
913 file, linenum, *res, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917
918 if (idle > 65535) {
919 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 global.tune.idle_timer = idle;
924 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100925 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
927 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100928 if (global.tune.client_rcvbuf != 0) {
929 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
930 err_code |= ERR_ALERT;
931 goto out;
932 }
933 if (*(args[1]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 global.tune.client_rcvbuf = atol(args[1]);
939 }
940 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200941 if (alertif_too_many_args(1, file, linenum, args, &err_code))
942 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100943 if (global.tune.server_rcvbuf != 0) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 global.tune.server_rcvbuf = atol(args[1]);
954 }
955 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100958 if (global.tune.client_sndbuf != 0) {
959 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
960 err_code |= ERR_ALERT;
961 goto out;
962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
967 }
968 global.tune.client_sndbuf = atol(args[1]);
969 }
970 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200971 if (alertif_too_many_args(1, file, linenum, args, &err_code))
972 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100973 if (global.tune.server_sndbuf != 0) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 global.tune.server_sndbuf = atol(args[1]);
984 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200985 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200986 if (alertif_too_many_args(1, file, linenum, args, &err_code))
987 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200988 if (*(args[1]) == 0) {
989 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto out;
992 }
993 global.tune.pipesize = atol(args[1]);
994 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100995 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
1002 }
1003 global.tune.cookie_len = atol(args[1]) + 1;
1004 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001005 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1007 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 global.tune.max_http_hdr = atol(args[1]);
1014 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001015 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1016#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001017 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1018 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001019 if (*args[1]) {
1020 global.tune.zlibmemlevel = atoi(args[1]);
1021 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1022 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1023 file, linenum, args[0]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027 } else {
1028 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1029 file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033#else
1034 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037#endif
1038 }
1039 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1040#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001041 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1042 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001043 if (*args[1]) {
1044 global.tune.zlibwindowsize = atoi(args[1]);
1045 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1046 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1047 file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050 }
1051 } else {
1052 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1053 file, linenum, args[0]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057#else
1058 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061#endif
1062 }
William Lallemandf3747832012-11-09 12:33:10 +01001063 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001064 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1065 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001066 if (*args[1]) {
1067 global.tune.comp_maxlevel = atoi(args[1]);
1068 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1069 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1070 file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 } else {
1075 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1076 file, linenum, args[0]);
1077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
1079 }
1080 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001081 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1082 if (*args[1]) {
1083 global.tune.pattern_cache = atoi(args[1]);
1084 if (global.tune.pattern_cache < 0) {
1085 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1086 file, linenum, args[0]);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto out;
1089 }
1090 } else {
1091 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1092 file, linenum, args[0]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001098 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001101 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001110 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1111 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]);
1112 err_code |= ERR_WARN;
1113 goto out;
1114 }
1115
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 }
1117 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001118 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001121 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT;
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001130 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1131 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]);
1132 err_code |= ERR_WARN;
1133 goto out;
1134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
Simon Horman98637e52014-06-20 12:30:16 +09001136 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001137 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1138 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001139 global.external_check = 1;
1140 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001141 /* user/group name handling */
1142 else if (!strcmp(args[0], "user")) {
1143 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001144 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1145 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001146 if (global.uid != 0) {
1147 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT;
1149 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001150 }
1151 errno = 0;
1152 ha_user = getpwnam(args[1]);
1153 if (ha_user != NULL) {
1154 global.uid = (int)ha_user->pw_uid;
1155 }
1156 else {
1157 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 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001159 }
1160 }
1161 else if (!strcmp(args[0], "group")) {
1162 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001163 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1164 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001165 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001166 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001167 err_code |= ERR_ALERT;
1168 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001169 }
1170 errno = 0;
1171 ha_group = getgrnam(args[1]);
1172 if (ha_group != NULL) {
1173 global.gid = (int)ha_group->gr_gid;
1174 }
1175 else {
1176 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 +02001177 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001178 }
1179 }
1180 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001181 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188 }
1189 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001190 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1191 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1192 file, linenum, args[0], LONGBITS, global.nbproc);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 }
1197 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (global.maxconn != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
1210 global.maxconn = atol(args[1]);
1211#ifdef SYSTEM_MAXCONN
1212 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1213 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);
1214 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001216 }
1217#endif /* SYSTEM_MAXCONN */
1218 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001219 else if (!strcmp(args[0], "maxsslconn")) {
1220#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001221 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1222 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001223 if (*(args[1]) == 0) {
1224 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228 global.maxsslconn = atol(args[1]);
1229#else
Emeric Brun0914df82012-10-02 18:45:42 +02001230 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001233#endif
1234 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001235 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1236#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001237 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1238 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001239 if (*(args[1]) == 0) {
1240 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244 free(global.listen_default_ciphers);
1245 global.listen_default_ciphers = strdup(args[1]);
1246#else
1247 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250#endif
1251 }
1252 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1253#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 free(global.connect_default_ciphers);
1262 global.connect_default_ciphers = strdup(args[1]);
1263#else
1264 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267#endif
1268 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001269#ifdef USE_OPENSSL
1270#ifndef OPENSSL_NO_DH
1271 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1272 if (*(args[1]) == 0) {
1273 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1278 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281 }
1282 }
1283#endif
1284#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001285 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001286 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1287 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001288 if (*(args[1]) == 0) {
1289 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293 if (strcmp(args[1],"none") == 0)
1294 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1295 else if (strcmp(args[1],"required") == 0)
1296 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1297 else {
1298 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001303 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001304 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1305 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001306 if (global.cps_lim != 0) {
1307 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1308 err_code |= ERR_ALERT;
1309 goto out;
1310 }
1311 if (*(args[1]) == 0) {
1312 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316 global.cps_lim = atol(args[1]);
1317 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001318 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001319 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1320 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001321 if (global.sps_lim != 0) {
1322 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1323 err_code |= ERR_ALERT;
1324 goto out;
1325 }
1326 if (*(args[1]) == 0) {
1327 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 global.sps_lim = atol(args[1]);
1332 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001333 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001334 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1335 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001336 if (global.ssl_lim != 0) {
1337 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1338 err_code |= ERR_ALERT;
1339 goto out;
1340 }
1341 if (*(args[1]) == 0) {
1342 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346 global.ssl_lim = atol(args[1]);
1347 }
William Lallemandd85f9172012-11-09 17:05:39 +01001348 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001349 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1350 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001351 if (*(args[1]) == 0) {
1352 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356 global.comp_rate_lim = atoi(args[1]) * 1024;
1357 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001358 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001361 if (global.maxpipes != 0) {
1362 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT;
1364 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001365 }
1366 if (*(args[1]) == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001370 }
1371 global.maxpipes = atol(args[1]);
1372 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001373 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001376 if (*(args[1]) == 0) {
1377 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto out;
1380 }
William Lallemande3a7d992012-11-20 11:25:20 +01001381 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001382 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001383 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001384 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1385 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001386 if (*(args[1]) == 0) {
1387 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1388 err_code |= ERR_ALERT | ERR_FATAL;
1389 goto out;
1390 }
1391 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001392 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001393 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
1396 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001397 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001400 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 if (global.rlimit_nofile != 0) {
1403 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001404 err_code |= ERR_ALERT;
1405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 }
1407 if (*(args[1]) == 0) {
1408 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 }
1412 global.rlimit_nofile = atol(args[1]);
1413 }
1414 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001415 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 if (global.chroot != NULL) {
1418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001419 err_code |= ERR_ALERT;
1420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 }
1422 if (*(args[1]) == 0) {
1423 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
1427 global.chroot = strdup(args[1]);
1428 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001429 else if (!strcmp(args[0], "description")) {
1430 int i, len=0;
1431 char *d;
1432
1433 if (!*args[1]) {
1434 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1435 file, linenum, args[0]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
Willy Tarreau348acfe2014-04-14 15:00:39 +02001440 for (i = 1; *args[i]; i++)
1441 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001442
1443 if (global.desc)
1444 free(global.desc);
1445
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001446 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001447
Willy Tarreau348acfe2014-04-14 15:00:39 +02001448 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1449 for (i = 2; *args[i]; i++)
1450 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001451 }
1452 else if (!strcmp(args[0], "node")) {
1453 int i;
1454 char c;
1455
William Lallemand1a748ae2015-05-19 16:37:23 +02001456 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1457 goto out;
1458
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001459 for (i=0; args[1][i]; i++) {
1460 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001461 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1462 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001463 break;
1464 }
1465
1466 if (!i || args[1][i]) {
1467 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1468 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1469 file, linenum, args[0]);
1470 err_code |= ERR_ALERT | ERR_FATAL;
1471 goto out;
1472 }
1473
1474 if (global.node)
1475 free(global.node);
1476
1477 global.node = strdup(args[1]);
1478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001480 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 if (global.pidfile != NULL) {
1483 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001484 err_code |= ERR_ALERT;
1485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 }
1487 if (*(args[1]) == 0) {
1488 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001489 err_code |= ERR_ALERT | ERR_FATAL;
1490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 }
1492 global.pidfile = strdup(args[1]);
1493 }
Emeric Bruned760922010-10-22 17:59:25 +02001494 else if (!strcmp(args[0], "unix-bind")) {
1495 int cur_arg = 1;
1496 while (*(args[cur_arg])) {
1497 if (!strcmp(args[cur_arg], "prefix")) {
1498 if (global.unix_bind.prefix != NULL) {
1499 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1500 err_code |= ERR_ALERT;
1501 cur_arg += 2;
1502 continue;
1503 }
1504
1505 if (*(args[cur_arg+1]) == 0) {
1506 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
1509 }
1510 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1511 cur_arg += 2;
1512 continue;
1513 }
1514
1515 if (!strcmp(args[cur_arg], "mode")) {
1516
1517 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1518 cur_arg += 2;
1519 continue;
1520 }
1521
1522 if (!strcmp(args[cur_arg], "uid")) {
1523
1524 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1525 cur_arg += 2;
1526 continue;
1527 }
1528
1529 if (!strcmp(args[cur_arg], "gid")) {
1530
1531 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1532 cur_arg += 2;
1533 continue;
1534 }
1535
1536 if (!strcmp(args[cur_arg], "user")) {
1537 struct passwd *user;
1538
1539 user = getpwnam(args[cur_arg + 1]);
1540 if (!user) {
1541 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1542 file, linenum, args[0], args[cur_arg + 1 ]);
1543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
1547 global.unix_bind.ux.uid = user->pw_uid;
1548 cur_arg += 2;
1549 continue;
1550 }
1551
1552 if (!strcmp(args[cur_arg], "group")) {
1553 struct group *group;
1554
1555 group = getgrnam(args[cur_arg + 1]);
1556 if (!group) {
1557 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1558 file, linenum, args[0], args[cur_arg + 1 ]);
1559 err_code |= ERR_ALERT | ERR_FATAL;
1560 goto out;
1561 }
1562
1563 global.unix_bind.ux.gid = group->gr_gid;
1564 cur_arg += 2;
1565 continue;
1566 }
1567
Willy Tarreaub48f9582011-09-05 01:17:06 +02001568 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001569 file, linenum, args[0]);
1570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
1572 }
1573 }
William Lallemand0f99e342011-10-12 17:50:54 +02001574 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1575 /* delete previous herited or defined syslog servers */
1576 struct logsrv *back;
1577 struct logsrv *tmp;
1578
1579 if (*(args[1]) != 0) {
1580 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1581 err_code |= ERR_ALERT | ERR_FATAL;
1582 goto out;
1583 }
1584
1585 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1586 LIST_DEL(&tmp->list);
1587 free(tmp);
1588 }
1589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001591 struct sockaddr_storage *sk;
1592 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001593 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001594 int arg = 0;
1595 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001596
William Lallemand1a748ae2015-05-19 16:37:23 +02001597 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1598 goto out;
1599
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 if (*(args[1]) == 0 || *(args[2]) == 0) {
1601 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001602 err_code |= ERR_ALERT | ERR_FATAL;
1603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
William Lallemand0f99e342011-10-12 17:50:54 +02001605
Vincent Bernat02779b62016-04-03 13:48:43 +02001606 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001607
Willy Tarreau18324f52014-06-27 18:10:07 +02001608 /* just after the address, a length may be specified */
1609 if (strcmp(args[arg+2], "len") == 0) {
1610 len = atoi(args[arg+3]);
1611 if (len < 80 || len > 65535) {
1612 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1613 file, linenum, args[arg+3]);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617 logsrv->maxlen = len;
1618
1619 /* skip these two args */
1620 arg += 2;
1621 }
1622 else
1623 logsrv->maxlen = MAX_SYSLOG_LEN;
1624
1625 if (logsrv->maxlen > global.max_syslog_len) {
1626 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001627 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1628 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1629 logline = my_realloc2(logline, global.max_syslog_len + 1);
1630 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001631 }
1632
Dragan Dosen1322d092015-09-22 16:05:32 +02001633 /* after the length, a format may be specified */
1634 if (strcmp(args[arg+2], "format") == 0) {
1635 logsrv->format = get_log_format(args[arg+3]);
1636 if (logsrv->format < 0) {
1637 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1638 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001639 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001640 goto out;
1641 }
1642
1643 /* skip these two args */
1644 arg += 2;
1645 }
1646
David Carlier97880bb2016-04-08 10:35:26 +01001647 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1648 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001649 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001650 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001651
Willy Tarreau18324f52014-06-27 18:10:07 +02001652 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001653 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001654 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001656 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 }
1658
William Lallemand0f99e342011-10-12 17:50:54 +02001659 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001660 if (*(args[arg+3])) {
1661 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001662 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001663 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001664 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001665 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001666 }
1667 }
1668
William Lallemand0f99e342011-10-12 17:50:54 +02001669 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001670 if (*(args[arg+4])) {
1671 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001672 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001673 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001675 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001676 }
1677 }
1678
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001679 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001680 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001681 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001682 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001683 free(logsrv);
1684 goto out;
1685 }
1686 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001687
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001688 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001689 if (port1 != port2) {
1690 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1691 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001692 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001693 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001694 goto out;
1695 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001696
William Lallemand0f99e342011-10-12 17:50:54 +02001697 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001698 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001699 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701
William Lallemand0f99e342011-10-12 17:50:54 +02001702 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001703 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001704 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1705 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001706
1707 if (global.log_send_hostname != NULL) {
1708 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1709 err_code |= ERR_ALERT;
1710 goto out;
1711 }
1712
1713 if (*(args[1]))
1714 name = args[1];
1715 else
1716 name = hostname;
1717
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001718 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001719 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001720 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001721 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1722 if (global.server_state_base != NULL) {
1723 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1724 err_code |= ERR_ALERT;
1725 goto out;
1726 }
1727
1728 if (!*(args[1])) {
1729 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1730 err_code |= ERR_FATAL;
1731 goto out;
1732 }
1733
1734 global.server_state_base = strdup(args[1]);
1735 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001736 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1737 if (global.server_state_file != NULL) {
1738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1739 err_code |= ERR_ALERT;
1740 goto out;
1741 }
1742
1743 if (!*(args[1])) {
1744 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1745 err_code |= ERR_FATAL;
1746 goto out;
1747 }
1748
1749 global.server_state_file = strdup(args[1]);
1750 }
Kevinm48936af2010-12-22 16:08:21 +00001751 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001752 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1753 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001754 if (*(args[1]) == 0) {
1755 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001759 chunk_destroy(&global.log_tag);
1760 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001761 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001762 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1764 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001765 if (global.spread_checks != 0) {
1766 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001767 err_code |= ERR_ALERT;
1768 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001769 }
1770 if (*(args[1]) == 0) {
1771 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001774 }
1775 global.spread_checks = atol(args[1]);
1776 if (global.spread_checks < 0 || global.spread_checks > 50) {
1777 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001778 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001781 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1782 const char *err;
1783 unsigned int val;
1784
William Lallemand1a748ae2015-05-19 16:37:23 +02001785 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1786 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001787 if (*(args[1]) == 0) {
1788 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792
1793 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1794 if (err) {
1795 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 }
1798 global.max_spread_checks = val;
1799 if (global.max_spread_checks < 0) {
1800 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 }
1803 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001804 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1805#ifdef USE_CPU_AFFINITY
1806 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001807 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001808 unsigned long cpus = 0;
1809
1810 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001811 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001812 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001813 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001814 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001815 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001816 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001817 proc = atol(args[1]);
1818 if (proc >= 1 && proc <= LONGBITS)
1819 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001820 }
1821
1822 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001823 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",
1824 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828
1829 cur_arg = 2;
1830 while (*args[cur_arg]) {
1831 unsigned int low, high;
1832
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001833 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001834 char *dash = strchr(args[cur_arg], '-');
1835
1836 low = high = str2uic(args[cur_arg]);
1837 if (dash)
1838 high = str2uic(dash + 1);
1839
1840 if (high < low) {
1841 unsigned int swap = low;
1842 low = high;
1843 high = swap;
1844 }
1845
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001846 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001847 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001848 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 }
1852
1853 while (low <= high)
1854 cpus |= 1UL << low++;
1855 }
1856 else {
1857 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1858 file, linenum, args[0], args[cur_arg]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862 cur_arg++;
1863 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001864 for (i = 0; i < LONGBITS; i++)
1865 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001866 global.cpu_map[i] = cpus;
1867#else
1868 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871#endif
1872 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001873 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1874 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1875 goto out;
1876
1877 if (*(args[2]) == 0) {
1878 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
1881 }
1882
1883 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1884 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1885 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
1888 }
1889 }
1890 else if (!strcmp(args[0], "unsetenv")) {
1891 int arg;
1892
1893 if (*(args[1]) == 0) {
1894 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
1897 }
1898
1899 for (arg = 1; *args[arg]; arg++) {
1900 if (unsetenv(args[arg]) != 0) {
1901 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905 }
1906 }
1907 else if (!strcmp(args[0], "resetenv")) {
1908 extern char **environ;
1909 char **env = environ;
1910
1911 /* args contain variable names to keep, one per argument */
1912 while (*env) {
1913 int arg;
1914
1915 /* look for current variable in among all those we want to keep */
1916 for (arg = 1; *args[arg]; arg++) {
1917 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1918 (*env)[strlen(args[arg])] == '=')
1919 break;
1920 }
1921
1922 /* delete this variable */
1923 if (!*args[arg]) {
1924 char *delim = strchr(*env, '=');
1925
1926 if (!delim || delim - *env >= trash.size) {
1927 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
1931
1932 memcpy(trash.str, *env, delim - *env);
1933 trash.str[delim - *env] = 0;
1934
1935 if (unsetenv(trash.str) != 0) {
1936 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1937 err_code |= ERR_ALERT | ERR_FATAL;
1938 goto out;
1939 }
1940 }
1941 else
1942 env++;
1943 }
1944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001946 struct cfg_kw_list *kwl;
1947 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001948 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001949
1950 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1951 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1952 if (kwl->kw[index].section != CFG_GLOBAL)
1953 continue;
1954 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001955 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001956 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001957 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001959 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001960 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001961 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001962 err_code |= ERR_WARN;
1963 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001964 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001965 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001966 }
1967 }
1968 }
1969
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001973
Willy Tarreau058e9072009-07-20 09:30:05 +02001974 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001975 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001976 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977}
1978
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001979void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001981 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 defproxy.mode = PR_MODE_TCP;
1983 defproxy.state = PR_STNEW;
1984 defproxy.maxconn = cfg_maxpconn;
1985 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001986 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001987 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001988
Simon Horman66183002013-02-23 10:16:43 +09001989 defproxy.defsrv.check.inter = DEF_CHKINTR;
1990 defproxy.defsrv.check.fastinter = 0;
1991 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001992 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1993 defproxy.defsrv.agent.fastinter = 0;
1994 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001995 defproxy.defsrv.check.rise = DEF_RISETIME;
1996 defproxy.defsrv.check.fall = DEF_FALLTIME;
1997 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1998 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001999 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09002000 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002001 defproxy.defsrv.maxqueue = 0;
2002 defproxy.defsrv.minconn = 0;
2003 defproxy.defsrv.maxconn = 0;
2004 defproxy.defsrv.slowstart = 0;
2005 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2006 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2007 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002008
2009 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002010 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011}
2012
Willy Tarreauade5ec42010-01-28 19:33:49 +01002013
Willy Tarreau63af98d2014-05-18 08:11:41 +02002014/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2015 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2016 * ERR_FATAL in case of error.
2017 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002018static int create_cond_regex_rule(const char *file, int line,
2019 struct proxy *px, int dir, int action, int flags,
2020 const char *cmd, const char *reg, const char *repl,
2021 const char **cond_start)
2022{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002023 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002024 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002025 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002026 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002028 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002029 int cs;
2030 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002031
2032 if (px == &defproxy) {
2033 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002034 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002035 goto err;
2036 }
2037
2038 if (*reg == 0) {
2039 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002040 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002041 goto err;
2042 }
2043
Christopher Faulet898566e2016-10-26 11:06:28 +02002044 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002045 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002046
Willy Tarreau5321c422010-01-28 20:35:13 +01002047 if (cond_start &&
2048 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002049 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2050 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2051 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002052 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002053 goto err;
2054 }
2055 }
2056 else if (cond_start && **cond_start) {
2057 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2058 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002059 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002060 goto err;
2061 }
2062
Willy Tarreau63af98d2014-05-18 08:11:41 +02002063 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002064 (dir == SMP_OPT_DIR_REQ) ?
2065 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2066 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2067 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002068
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002069 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002070 if (!preg) {
2071 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002072 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002073 goto err;
2074 }
2075
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002076 cs = !(flags & REG_ICASE);
2077 cap = !(flags & REG_NOSUB);
2078 error = NULL;
2079 if (!regex_comp(reg, preg, cs, cap, &error)) {
2080 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2081 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002082 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002083 goto err;
2084 }
2085
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002086 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002087 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002088 if (repl && err) {
2089 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2090 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002091 ret_code |= ERR_ALERT | ERR_FATAL;
2092 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002093 }
2094
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002095 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002096 ret_code |= ERR_WARN;
2097
2098 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002099
Willy Tarreau63af98d2014-05-18 08:11:41 +02002100 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002101 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002102 err:
2103 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002104 free(errmsg);
2105 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002106}
2107
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108/*
William Lallemand51097192015-04-14 16:35:22 +02002109 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002110 * Returns the error code, 0 if OK, or any combination of :
2111 * - ERR_ABORT: must abort ASAP
2112 * - ERR_FATAL: we can continue parsing but not start the service
2113 * - ERR_WARN: a warning has been emitted
2114 * - ERR_ALERT: an alert has been emitted
2115 * Only the two first ones can stop processing, the two others are just
2116 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002118int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2119{
2120 static struct peers *curpeers = NULL;
2121 struct peer *newpeer = NULL;
2122 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002123 struct bind_conf *bind_conf;
2124 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002126 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127
2128 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002129 if (!*args[1]) {
2130 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002131 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002132 goto out;
2133 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002134
William Lallemand6e62fb62015-04-28 16:55:23 +02002135 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2136 goto out;
2137
Emeric Brun32da3c42010-09-23 18:39:19 +02002138 err = invalid_char(args[1]);
2139 if (err) {
2140 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2141 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002142 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002143 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002144 }
2145
2146 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2147 /*
2148 * If there are two proxies with the same name only following
2149 * combinations are allowed:
2150 */
2151 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002152 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 +02002153 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002155 }
2156 }
2157
Vincent Bernat02779b62016-04-03 13:48:43 +02002158 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002159 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2160 err_code |= ERR_ALERT | ERR_ABORT;
2161 goto out;
2162 }
2163
2164 curpeers->next = peers;
2165 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002166 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002167 curpeers->conf.line = linenum;
2168 curpeers->last_change = now.tv_sec;
2169 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002170 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002171 }
2172 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002173 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002174 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002175 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002176
2177 if (!*args[2]) {
2178 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2179 file, linenum, args[0]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
2183
2184 err = invalid_char(args[1]);
2185 if (err) {
2186 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2187 file, linenum, *err, args[1]);
2188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
2191
Vincent Bernat02779b62016-04-03 13:48:43 +02002192 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2194 err_code |= ERR_ALERT | ERR_ABORT;
2195 goto out;
2196 }
2197
2198 /* the peers are linked backwards first */
2199 curpeers->count++;
2200 newpeer->next = curpeers->remote;
2201 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002202 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002203 newpeer->conf.line = linenum;
2204
2205 newpeer->last_change = now.tv_sec;
2206 newpeer->id = strdup(args[1]);
2207
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002208 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002209 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002210 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002213 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002214
2215 proto = protocol_by_family(sk->ss_family);
2216 if (!proto || !proto->connect) {
2217 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2218 file, linenum, args[0], args[1]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002222
2223 if (port1 != port2) {
2224 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2225 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
2228 }
2229
Willy Tarreau2aa38802013-02-20 19:20:59 +01002230 if (!port1) {
2231 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2232 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002236
Emeric Brun32da3c42010-09-23 18:39:19 +02002237 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002238 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002239 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002240 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002241
Emeric Brun32da3c42010-09-23 18:39:19 +02002242 if (strcmp(newpeer->id, localpeer) == 0) {
2243 /* Current is local peer, it define a frontend */
2244 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002245 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002246
2247 if (!curpeers->peers_fe) {
2248 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2250 err_code |= ERR_ALERT | ERR_ABORT;
2251 goto out;
2252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002253
Willy Tarreau237250c2011-07-29 01:49:03 +02002254 init_new_proxy(curpeers->peers_fe);
2255 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002256 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002257 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2258 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002259 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002260
2261 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2262
Willy Tarreau902636f2013-03-10 19:44:48 +01002263 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2264 if (errmsg && *errmsg) {
2265 indent_msg(&errmsg, 2);
2266 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002267 }
2268 else
2269 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2270 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002271 err_code |= ERR_FATAL;
2272 goto out;
2273 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002274
2275 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002276 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002277 l->maxconn = curpeers->peers_fe->maxconn;
2278 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002279 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002280 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002281 l->analysers |= curpeers->peers_fe->fe_req_ana;
2282 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002283 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2284 global.maxsock += l->maxconn;
2285 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002286 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002287 else {
2288 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2289 file, linenum, args[0], args[1],
2290 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2291 err_code |= ERR_FATAL;
2292 goto out;
2293 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002294 }
2295 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002296 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2297 curpeers->state = PR_STSTOPPED;
2298 }
2299 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2300 curpeers->state = PR_STNEW;
2301 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002302 else if (*args[0] != 0) {
2303 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
2307
2308out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002309 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002310 return err_code;
2311}
2312
Baptiste Assmann325137d2015-04-13 23:40:55 +02002313/*
2314 * Parse a <resolvers> section.
2315 * Returns the error code, 0 if OK, or any combination of :
2316 * - ERR_ABORT: must abort ASAP
2317 * - ERR_FATAL: we can continue parsing but not start the service
2318 * - ERR_WARN: a warning has been emitted
2319 * - ERR_ALERT: an alert has been emitted
2320 * Only the two first ones can stop processing, the two others are just
2321 * indicators.
2322 */
2323int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2324{
2325 static struct dns_resolvers *curr_resolvers = NULL;
2326 struct dns_nameserver *newnameserver = NULL;
2327 const char *err;
2328 int err_code = 0;
2329 char *errmsg = NULL;
2330
2331 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2332 if (!*args[1]) {
2333 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2334 err_code |= ERR_ALERT | ERR_ABORT;
2335 goto out;
2336 }
2337
2338 err = invalid_char(args[1]);
2339 if (err) {
2340 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2341 file, linenum, *err, args[0], args[1]);
2342 err_code |= ERR_ALERT | ERR_ABORT;
2343 goto out;
2344 }
2345
2346 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2347 /* Error if two resolvers owns the same name */
2348 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2349 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2350 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2351 err_code |= ERR_ALERT | ERR_ABORT;
2352 }
2353 }
2354
Vincent Bernat02779b62016-04-03 13:48:43 +02002355 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002356 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2357 err_code |= ERR_ALERT | ERR_ABORT;
2358 goto out;
2359 }
2360
2361 /* default values */
2362 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2363 curr_resolvers->conf.file = strdup(file);
2364 curr_resolvers->conf.line = linenum;
2365 curr_resolvers->id = strdup(args[1]);
2366 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002367 /* default hold period for nx, other, refuse and timeout is 30s */
2368 curr_resolvers->hold.nx = 30000;
2369 curr_resolvers->hold.other = 30000;
2370 curr_resolvers->hold.refused = 30000;
2371 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002372 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002373 curr_resolvers->hold.valid = 10000;
2374 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002375 curr_resolvers->resolve_retries = 3;
2376 LIST_INIT(&curr_resolvers->nameserver_list);
2377 LIST_INIT(&curr_resolvers->curr_resolution);
2378 }
2379 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2380 struct sockaddr_storage *sk;
2381 int port1, port2;
2382 struct protocol *proto;
2383
2384 if (!*args[2]) {
2385 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2386 file, linenum, args[0]);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 err = invalid_char(args[1]);
2392 if (err) {
2393 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2394 file, linenum, *err, args[1]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398
Baptiste Assmanna315c552015-11-02 22:55:49 +01002399 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2400 /* Error if two resolvers owns the same name */
2401 if (strcmp(newnameserver->id, args[1]) == 0) {
2402 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2403 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2404 err_code |= ERR_ALERT | ERR_FATAL;
2405 }
2406 }
2407
Vincent Bernat02779b62016-04-03 13:48:43 +02002408 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002409 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2410 err_code |= ERR_ALERT | ERR_ABORT;
2411 goto out;
2412 }
2413
2414 /* the nameservers are linked backward first */
2415 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2416 curr_resolvers->count_nameservers++;
2417 newnameserver->resolvers = curr_resolvers;
2418 newnameserver->conf.file = strdup(file);
2419 newnameserver->conf.line = linenum;
2420 newnameserver->id = strdup(args[1]);
2421
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002422 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002423 if (!sk) {
2424 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428
2429 proto = protocol_by_family(sk->ss_family);
2430 if (!proto || !proto->connect) {
2431 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2432 file, linenum, args[0], args[1]);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436
2437 if (port1 != port2) {
2438 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2439 file, linenum, args[0], args[1], args[2]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002444 if (!port1 && !port2) {
2445 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2446 file, linenum, args[0], args[1]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
Baptiste Assmann325137d2015-04-13 23:40:55 +02002451 newnameserver->addr = *sk;
2452 }
2453 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2454 const char *res;
2455 unsigned int time;
2456
2457 if (!*args[2]) {
2458 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2459 file, linenum, args[0]);
2460 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2465 if (res) {
2466 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2467 file, linenum, *res, args[0]);
2468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
2470 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002471 if (strcmp(args[1], "nx") == 0)
2472 curr_resolvers->hold.nx = time;
2473 else if (strcmp(args[1], "other") == 0)
2474 curr_resolvers->hold.other = time;
2475 else if (strcmp(args[1], "refused") == 0)
2476 curr_resolvers->hold.refused = time;
2477 else if (strcmp(args[1], "timeout") == 0)
2478 curr_resolvers->hold.timeout = time;
2479 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002480 curr_resolvers->hold.valid = time;
2481 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002482 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2483 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
2488 }
2489 else if (strcmp(args[0], "resolve_retries") == 0) {
2490 if (!*args[1]) {
2491 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2492 file, linenum, args[0]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496 curr_resolvers->resolve_retries = atoi(args[1]);
2497 }
2498 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002499 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002500 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2501 file, linenum, args[0]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002505 else if (strcmp(args[1], "retry") == 0) {
2506 const char *res;
2507 unsigned int timeout_retry;
2508
2509 if (!*args[2]) {
2510 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2511 file, linenum, args[0], args[1]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2516 if (res) {
2517 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2518 file, linenum, *res, args[0], args[1]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522 curr_resolvers->timeout.retry = timeout_retry;
2523 }
2524 else {
2525 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2526 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
2529 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002530 } /* neither "nameserver" nor "resolvers" */
2531 else if (*args[0] != 0) {
2532 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
2535 }
2536
2537 out:
2538 free(errmsg);
2539 return err_code;
2540}
Simon Horman0d16a402015-01-30 11:22:58 +09002541
2542/*
William Lallemand51097192015-04-14 16:35:22 +02002543 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002544 * Returns the error code, 0 if OK, or any combination of :
2545 * - ERR_ABORT: must abort ASAP
2546 * - ERR_FATAL: we can continue parsing but not start the service
2547 * - ERR_WARN: a warning has been emitted
2548 * - ERR_ALERT: an alert has been emitted
2549 * Only the two first ones can stop processing, the two others are just
2550 * indicators.
2551 */
2552int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2553{
2554 static struct mailers *curmailers = NULL;
2555 struct mailer *newmailer = NULL;
2556 const char *err;
2557 int err_code = 0;
2558 char *errmsg = NULL;
2559
2560 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2561 if (!*args[1]) {
2562 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
2565 }
2566
2567 err = invalid_char(args[1]);
2568 if (err) {
2569 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2570 file, linenum, *err, args[0], args[1]);
2571 err_code |= ERR_ALERT | ERR_ABORT;
2572 goto out;
2573 }
2574
2575 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2576 /*
2577 * If there are two proxies with the same name only following
2578 * combinations are allowed:
2579 */
2580 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002581 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 +09002582 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002584 }
2585 }
2586
Vincent Bernat02779b62016-04-03 13:48:43 +02002587 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002588 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2589 err_code |= ERR_ALERT | ERR_ABORT;
2590 goto out;
2591 }
2592
2593 curmailers->next = mailers;
2594 mailers = curmailers;
2595 curmailers->conf.file = strdup(file);
2596 curmailers->conf.line = linenum;
2597 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002598 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2599 * But need enough time so that timeouts don't occur
2600 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002601 }
2602 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2603 struct sockaddr_storage *sk;
2604 int port1, port2;
2605 struct protocol *proto;
2606
2607 if (!*args[2]) {
2608 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2609 file, linenum, args[0]);
2610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
2612 }
2613
2614 err = invalid_char(args[1]);
2615 if (err) {
2616 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2617 file, linenum, *err, args[1]);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621
Vincent Bernat02779b62016-04-03 13:48:43 +02002622 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002623 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2624 err_code |= ERR_ALERT | ERR_ABORT;
2625 goto out;
2626 }
2627
2628 /* the mailers are linked backwards first */
2629 curmailers->count++;
2630 newmailer->next = curmailers->mailer_list;
2631 curmailers->mailer_list = newmailer;
2632 newmailer->mailers = curmailers;
2633 newmailer->conf.file = strdup(file);
2634 newmailer->conf.line = linenum;
2635
2636 newmailer->id = strdup(args[1]);
2637
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002638 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002639 if (!sk) {
2640 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002646 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2647 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002648 file, linenum, args[0], args[1]);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652
2653 if (port1 != port2) {
2654 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2655 file, linenum, args[0], args[1], args[2]);
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
2658 }
2659
2660 if (!port1) {
2661 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2662 file, linenum, args[0], args[1], args[2]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 newmailer->addr = *sk;
2668 newmailer->proto = proto;
2669 newmailer->xprt = &raw_sock;
2670 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002671 }
2672 else if (strcmp(args[0], "timeout") == 0) {
2673 if (!*args[1]) {
2674 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2675 file, linenum, args[0]);
2676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
2678 }
2679 else if (strcmp(args[1], "mail") == 0) {
2680 const char *res;
2681 unsigned int timeout_mail;
2682 if (!*args[2]) {
2683 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2684 file, linenum, args[0], args[1]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2689 if (res) {
2690 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2691 file, linenum, *res, args[0]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695 if (timeout_mail <= 0) {
2696 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700 curmailers->timeout.mail = timeout_mail;
2701 } else {
2702 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2703 file, linenum, args[0], args[1]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707 }
Simon Horman0d16a402015-01-30 11:22:58 +09002708 else if (*args[0] != 0) {
2709 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713
2714out:
2715 free(errmsg);
2716 return err_code;
2717}
2718
Simon Horman9dc49962015-01-30 11:22:59 +09002719static void free_email_alert(struct proxy *p)
2720{
2721 free(p->email_alert.mailers.name);
2722 p->email_alert.mailers.name = NULL;
2723 free(p->email_alert.from);
2724 p->email_alert.from = NULL;
2725 free(p->email_alert.to);
2726 p->email_alert.to = NULL;
2727 free(p->email_alert.myhostname);
2728 p->email_alert.myhostname = NULL;
2729}
2730
Willy Tarreau3842f002009-06-14 11:39:52 +02002731int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732{
2733 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002734 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002735 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002736 int rc;
2737 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002738 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002739 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002740 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002741 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002742 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 if (!strcmp(args[0], "listen"))
2745 rc = PR_CAP_LISTEN;
2746 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002747 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002748 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002749 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002750 else
2751 rc = PR_CAP_NONE;
2752
2753 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 if (!*args[1]) {
2755 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002756 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_ABORT;
2759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002761
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002762 err = invalid_char(args[1]);
2763 if (err) {
2764 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2765 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002767 }
2768
Willy Tarreau8f50b682015-05-26 11:45:02 +02002769 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2770 if (curproxy) {
2771 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2772 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2773 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002775 }
2776
Vincent Bernat02779b62016-04-03 13:48:43 +02002777 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_ALERT | ERR_ABORT;
2780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002782
Willy Tarreau97cb7802010-01-03 20:23:58 +01002783 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 curproxy->next = proxy;
2785 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002786 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2787 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002788 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002791 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792
William Lallemand6e62fb62015-04-28 16:55:23 +02002793 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2794 if (curproxy->cap & PR_CAP_FE)
2795 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 }
2798
2799 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002800 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002801 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002802
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002805 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002806 curproxy->no_options = defproxy.no_options;
2807 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002808 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002809 curproxy->except_net = defproxy.except_net;
2810 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002811 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002812 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002814 if (defproxy.fwdfor_hdr_len) {
2815 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2816 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2817 }
2818
Willy Tarreaub86db342009-11-30 11:50:16 +01002819 if (defproxy.orgto_hdr_len) {
2820 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2821 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2822 }
2823
Mark Lamourinec2247f02012-01-04 13:02:01 -05002824 if (defproxy.server_id_hdr_len) {
2825 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2826 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2827 }
2828
Willy Tarreau977b8e42006-12-29 14:19:17 +01002829 if (curproxy->cap & PR_CAP_FE) {
2830 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002831 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002832 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002833
2834 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2836 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002837
2838 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840
Willy Tarreau977b8e42006-12-29 14:19:17 +01002841 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002842 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002843 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002844 curproxy->fullconn = defproxy.fullconn;
2845 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002846 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002847 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002849 if (defproxy.check_req) {
2850 curproxy->check_req = calloc(1, defproxy.check_len);
2851 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2852 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002855 if (defproxy.expect_str) {
2856 curproxy->expect_str = strdup(defproxy.expect_str);
2857 if (defproxy.expect_regex) {
2858 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002859 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2860 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002861 }
2862 }
2863
Willy Tarreau67402132012-05-31 20:40:20 +02002864 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 if (defproxy.cookie_name)
2866 curproxy->cookie_name = strdup(defproxy.cookie_name);
2867 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002868 if (defproxy.cookie_domain)
2869 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002870
Willy Tarreau31936852010-10-06 16:59:56 +02002871 if (defproxy.cookie_maxidle)
2872 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2873
2874 if (defproxy.cookie_maxlife)
2875 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2876
Emeric Brun647caf12009-06-30 17:57:00 +02002877 if (defproxy.rdp_cookie_name)
2878 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2879 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2880
Willy Tarreau01732802007-11-01 22:48:15 +01002881 if (defproxy.url_param_name)
2882 curproxy->url_param_name = strdup(defproxy.url_param_name);
2883 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002884
Benoitaffb4812009-03-25 13:02:10 +01002885 if (defproxy.hh_name)
2886 curproxy->hh_name = strdup(defproxy.hh_name);
2887 curproxy->hh_len = defproxy.hh_len;
2888 curproxy->hh_match_domain = defproxy.hh_match_domain;
2889
Willy Tarreauef9a3602012-12-08 22:29:20 +01002890 if (defproxy.conn_src.iface_name)
2891 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2892 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002893 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002894#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002895 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002896#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002897 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002900 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901 if (defproxy.capture_name)
2902 curproxy->capture_name = strdup(defproxy.capture_name);
2903 curproxy->capture_namelen = defproxy.capture_namelen;
2904 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002908 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002909 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002910 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002911 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002912 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913 curproxy->mon_net = defproxy.mon_net;
2914 curproxy->mon_mask = defproxy.mon_mask;
2915 if (defproxy.monitor_uri)
2916 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2917 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002918 if (defproxy.defbe.name)
2919 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002920
2921 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002922 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2923 if (curproxy->conf.logformat_string &&
2924 curproxy->conf.logformat_string != default_http_log_format &&
2925 curproxy->conf.logformat_string != default_tcp_log_format &&
2926 curproxy->conf.logformat_string != clf_http_log_format)
2927 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2928
2929 if (defproxy.conf.lfs_file) {
2930 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2931 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2932 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002933
2934 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2935 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2936 if (curproxy->conf.logformat_sd_string &&
2937 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2938 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2939
2940 if (defproxy.conf.lfsd_file) {
2941 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2942 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944 }
2945
2946 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002947 curproxy->timeout.connect = defproxy.timeout.connect;
2948 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002949 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002950 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002951 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002952 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002953 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002954 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002955 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002956 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957 }
2958
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002960 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002961
2962 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002963 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002964 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002965 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002966 LIST_INIT(&node->list);
2967 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2968 }
2969
Willy Tarreau62a61232013-04-12 18:13:46 +02002970 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2971 if (curproxy->conf.uniqueid_format_string)
2972 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2973
Dragan Dosen43885c72015-10-01 13:18:13 +02002974 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002975
Willy Tarreau62a61232013-04-12 18:13:46 +02002976 if (defproxy.conf.uif_file) {
2977 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2978 curproxy->conf.uif_line = defproxy.conf.uif_line;
2979 }
William Lallemanda73203e2012-03-12 12:48:57 +01002980
2981 /* copy default header unique id */
2982 if (defproxy.header_unique_id)
2983 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2984
William Lallemand82fe75c2012-10-23 10:25:10 +02002985 /* default compression options */
2986 if (defproxy.comp != NULL) {
2987 curproxy->comp = calloc(1, sizeof(struct comp));
2988 curproxy->comp->algos = defproxy.comp->algos;
2989 curproxy->comp->types = defproxy.comp->types;
2990 }
2991
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002993 curproxy->conf.used_listener_id = EB_ROOT;
2994 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002995
Simon Horman98637e52014-06-20 12:30:16 +09002996 if (defproxy.check_path)
2997 curproxy->check_path = strdup(defproxy.check_path);
2998 if (defproxy.check_command)
2999 curproxy->check_command = strdup(defproxy.check_command);
3000
Simon Horman9dc49962015-01-30 11:22:59 +09003001 if (defproxy.email_alert.mailers.name)
3002 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
3003 if (defproxy.email_alert.from)
3004 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
3005 if (defproxy.email_alert.to)
3006 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
3007 if (defproxy.email_alert.myhostname)
3008 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09003009 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01003010 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09003011
Willy Tarreau93893792009-07-23 13:19:11 +02003012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
3014 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
3015 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003016 /* FIXME-20070101: we should do this too at the end of the
3017 * config parsing to free all default values.
3018 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003019 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3020 err_code |= ERR_ABORT;
3021 goto out;
3022 }
3023
Willy Tarreaua534fea2008-08-03 12:19:50 +02003024 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003025 free(defproxy.check_command);
3026 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003027 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003028 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003029 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003030 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003031 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003032 free(defproxy.capture_name);
3033 free(defproxy.monitor_uri);
3034 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003035 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003036 free(defproxy.fwdfor_hdr_name);
3037 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003038 free(defproxy.orgto_hdr_name);
3039 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003040 free(defproxy.server_id_hdr_name);
3041 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003042 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003043 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003044 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003045 free(defproxy.expect_regex);
3046 defproxy.expect_regex = NULL;
3047 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003048
Willy Tarreau62a61232013-04-12 18:13:46 +02003049 if (defproxy.conf.logformat_string != default_http_log_format &&
3050 defproxy.conf.logformat_string != default_tcp_log_format &&
3051 defproxy.conf.logformat_string != clf_http_log_format)
3052 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003053
Willy Tarreau62a61232013-04-12 18:13:46 +02003054 free(defproxy.conf.uniqueid_format_string);
3055 free(defproxy.conf.lfs_file);
3056 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003057 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003058 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003059
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003060 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3061 free(defproxy.conf.logformat_sd_string);
3062 free(defproxy.conf.lfsd_file);
3063
Willy Tarreaua534fea2008-08-03 12:19:50 +02003064 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003065 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003066
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 /* we cannot free uri_auth because it might already be used */
3068 init_default_instance();
3069 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003070 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3071 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003072 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075 else if (curproxy == NULL) {
3076 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003080
3081 /* update the current file and line being parsed */
3082 curproxy->conf.args.file = curproxy->conf.file;
3083 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084
3085 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003086 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3087 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3088 if (err_code & ERR_FATAL)
3089 goto out;
3090 }
3091 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003092 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003093 int cur_arg;
3094
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 if (curproxy == &defproxy) {
3096 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003100 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102
Willy Tarreau24709282013-03-10 21:32:12 +01003103 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003104 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003109
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003110 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003111
3112 /* use default settings for unix sockets */
3113 bind_conf->ux.uid = global.unix_bind.ux.uid;
3114 bind_conf->ux.gid = global.unix_bind.ux.gid;
3115 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003116
3117 /* NOTE: the following line might create several listeners if there
3118 * are comma-separated IPs or port ranges. So all further processing
3119 * will have to be applied to all listeners created after last_listen.
3120 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003121 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3122 if (errmsg && *errmsg) {
3123 indent_msg(&errmsg, 2);
3124 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003125 }
3126 else
3127 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3128 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
3131 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003132
Willy Tarreau4348fad2012-09-20 16:48:07 +02003133 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3134 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003135 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003136 }
3137
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003138 cur_arg = 2;
3139 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003140 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003141 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003142 char *err;
3143
Willy Tarreau26982662012-09-12 23:17:10 +02003144 kw = bind_find_kw(args[cur_arg]);
3145 if (kw) {
3146 char *err = NULL;
3147 int code;
3148
3149 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003150 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3151 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003152 cur_arg += 1 + kw->skip ;
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156
Willy Tarreau4348fad2012-09-20 16:48:07 +02003157 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003158 err_code |= code;
3159
3160 if (code) {
3161 if (err && *err) {
3162 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003163 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003164 }
3165 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003166 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3167 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003168 if (code & ERR_FATAL) {
3169 free(err);
3170 cur_arg += 1 + kw->skip;
3171 goto out;
3172 }
3173 }
3174 free(err);
3175 cur_arg += 1 + kw->skip;
3176 continue;
3177 }
3178
Willy Tarreau8638f482012-09-18 18:01:17 +02003179 err = NULL;
3180 if (!bind_dumped) {
3181 bind_dump_kws(&err);
3182 indent_msg(&err, 4);
3183 bind_dumped = 1;
3184 }
3185
3186 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3187 file, linenum, args[0], args[1], args[cur_arg],
3188 err ? " Registered keywords :" : "", err ? err : "");
3189 free(err);
3190
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003193 }
Willy Tarreau93893792009-07-23 13:19:11 +02003194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003197 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3199 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003203 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003205
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 /* flush useless bits */
3207 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003210 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003211 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003213
William Lallemanddf1425a2015-04-28 20:17:49 +02003214 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3215 goto out;
3216
Willy Tarreau1c47f852006-07-09 08:22:27 +02003217 if (!*args[1]) {
3218 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003222 }
3223
Willy Tarreaua534fea2008-08-03 12:19:50 +02003224 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003225 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003226 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003227 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003228 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3229
Willy Tarreau93893792009-07-23 13:19:11 +02003230 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003233 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3234 goto out;
3235
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3237 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3238 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3239 else {
3240 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
3244 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003245 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003246 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003247
3248 if (curproxy == &defproxy) {
3249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003253 }
3254
William Lallemanddf1425a2015-04-28 20:17:49 +02003255 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3256 goto out;
3257
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003258 if (!*args[1]) {
3259 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003263 }
3264
3265 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003266 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003267 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003268
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003269 if (curproxy->uuid <= 0) {
3270 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003271 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003274 }
3275
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003276 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3277 if (node) {
3278 struct proxy *target = container_of(node, struct proxy, conf.id);
3279 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3280 file, linenum, proxy_type_str(curproxy), curproxy->id,
3281 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284 }
3285 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003286 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003287 else if (!strcmp(args[0], "description")) {
3288 int i, len=0;
3289 char *d;
3290
Cyril Bonté99ed3272010-01-24 23:29:44 +01003291 if (curproxy == &defproxy) {
3292 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3293 file, linenum, args[0]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003298 if (!*args[1]) {
3299 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3300 file, linenum, args[0]);
3301 return -1;
3302 }
3303
Willy Tarreau348acfe2014-04-14 15:00:39 +02003304 for (i = 1; *args[i]; i++)
3305 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003306
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003307 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003308 curproxy->desc = d;
3309
Willy Tarreau348acfe2014-04-14 15:00:39 +02003310 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3311 for (i = 2; *args[i]; i++)
3312 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003313
3314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003316 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 curproxy->state = PR_STSTOPPED;
3319 }
3320 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003321 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 curproxy->state = PR_STNEW;
3324 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003325 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3326 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003327 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003328
3329 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003330 unsigned int low, high;
3331
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003332 if (strcmp(args[cur_arg], "all") == 0) {
3333 set = 0;
3334 break;
3335 }
3336 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003337 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003338 }
3339 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003340 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003341 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003342 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003343 char *dash = strchr(args[cur_arg], '-');
3344
3345 low = high = str2uic(args[cur_arg]);
3346 if (dash)
3347 high = str2uic(dash + 1);
3348
3349 if (high < low) {
3350 unsigned int swap = low;
3351 low = high;
3352 high = swap;
3353 }
3354
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003355 if (low < 1 || high > LONGBITS) {
3356 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3357 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003360 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003361 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003362 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003363 }
3364 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003365 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3366 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003369 }
3370 cur_arg++;
3371 }
3372 curproxy->bind_proc = set;
3373 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003374 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003375 if (curproxy == &defproxy) {
3376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003379 }
3380
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003381 err = invalid_char(args[1]);
3382 if (err) {
3383 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3384 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003386 }
3387
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003388 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003389 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3390 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003393 }
3394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3396 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397
Willy Tarreau977b8e42006-12-29 14:19:17 +01003398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003400
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 if (*(args[1]) == 0) {
3402 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003407
Willy Tarreau67402132012-05-31 20:40:20 +02003408 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003409 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003410 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003411 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 curproxy->cookie_name = strdup(args[1]);
3413 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003414
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 cur_arg = 2;
3416 while (*(args[cur_arg])) {
3417 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003418 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
3420 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003421 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 }
3423 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003424 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 }
3426 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003427 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
3429 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003430 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003432 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003433 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003436 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003438 else if (!strcmp(args[cur_arg], "httponly")) {
3439 curproxy->ck_opts |= PR_CK_HTTPONLY;
3440 }
3441 else if (!strcmp(args[cur_arg], "secure")) {
3442 curproxy->ck_opts |= PR_CK_SECURE;
3443 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003444 else if (!strcmp(args[cur_arg], "domain")) {
3445 if (!*args[cur_arg + 1]) {
3446 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3447 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003450 }
3451
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003452 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003453 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003454 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3455 " dots nor does not start with a dot."
3456 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003457 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003458 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003459 }
3460
3461 err = invalid_domainchar(args[cur_arg + 1]);
3462 if (err) {
3463 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3464 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003467 }
3468
Willy Tarreau68a897b2009-12-03 23:28:34 +01003469 if (!curproxy->cookie_domain) {
3470 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3471 } else {
3472 /* one domain was already specified, add another one by
3473 * building the string which will be returned along with
3474 * the cookie.
3475 */
3476 char *new_ptr;
3477 int new_len = strlen(curproxy->cookie_domain) +
3478 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3479 new_ptr = malloc(new_len);
3480 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3481 free(curproxy->cookie_domain);
3482 curproxy->cookie_domain = new_ptr;
3483 }
Willy Tarreau31936852010-10-06 16:59:56 +02003484 cur_arg++;
3485 }
3486 else if (!strcmp(args[cur_arg], "maxidle")) {
3487 unsigned int maxidle;
3488 const char *res;
3489
3490 if (!*args[cur_arg + 1]) {
3491 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3492 file, linenum, args[cur_arg]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496
3497 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3498 if (res) {
3499 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3500 file, linenum, *res, args[cur_arg]);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
3504 curproxy->cookie_maxidle = maxidle;
3505 cur_arg++;
3506 }
3507 else if (!strcmp(args[cur_arg], "maxlife")) {
3508 unsigned int maxlife;
3509 const char *res;
3510
3511 if (!*args[cur_arg + 1]) {
3512 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3513 file, linenum, args[cur_arg]);
3514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
3516 }
3517
3518 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3519 if (res) {
3520 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3521 file, linenum, *res, args[cur_arg]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003526 cur_arg++;
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003529 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 +02003530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
3534 cur_arg++;
3535 }
Willy Tarreau67402132012-05-31 20:40:20 +02003536 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3538 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541
Willy Tarreau67402132012-05-31 20:40:20 +02003542 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3544 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003547
Willy Tarreau67402132012-05-31 20:40:20 +02003548 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003549 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3550 file, linenum);
3551 err_code |= ERR_ALERT | ERR_FATAL;
3552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003554 else if (!strcmp(args[0], "email-alert")) {
3555 if (*(args[1]) == 0) {
3556 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3557 file, linenum, args[0]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561
3562 if (!strcmp(args[1], "from")) {
3563 if (*(args[1]) == 0) {
3564 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3565 file, linenum, args[1]);
3566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
3568 }
3569 free(curproxy->email_alert.from);
3570 curproxy->email_alert.from = strdup(args[2]);
3571 }
3572 else if (!strcmp(args[1], "mailers")) {
3573 if (*(args[1]) == 0) {
3574 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3575 file, linenum, args[1]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579 free(curproxy->email_alert.mailers.name);
3580 curproxy->email_alert.mailers.name = strdup(args[2]);
3581 }
3582 else if (!strcmp(args[1], "myhostname")) {
3583 if (*(args[1]) == 0) {
3584 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3585 file, linenum, args[1]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 free(curproxy->email_alert.myhostname);
3590 curproxy->email_alert.myhostname = strdup(args[2]);
3591 }
Simon Horman64e34162015-02-06 11:11:57 +09003592 else if (!strcmp(args[1], "level")) {
3593 curproxy->email_alert.level = get_log_level(args[2]);
3594 if (curproxy->email_alert.level < 0) {
3595 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3596 file, linenum, args[1], args[2]);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600 }
Simon Horman9dc49962015-01-30 11:22:59 +09003601 else if (!strcmp(args[1], "to")) {
3602 if (*(args[1]) == 0) {
3603 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3604 file, linenum, args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 free(curproxy->email_alert.to);
3609 curproxy->email_alert.to = strdup(args[2]);
3610 }
3611 else {
3612 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3613 file, linenum, args[1]);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
3616 }
Simon Horman64e34162015-02-06 11:11:57 +09003617 /* Indicate that the email_alert is at least partially configured */
3618 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003619 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003620 else if (!strcmp(args[0], "external-check")) {
3621 if (*(args[1]) == 0) {
3622 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3623 file, linenum, args[0]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627
3628 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003629 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003630 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003631 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003632 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3633 file, linenum, args[1]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637 free(curproxy->check_command);
3638 curproxy->check_command = strdup(args[2]);
3639 }
3640 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003641 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003642 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003643 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003644 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3645 file, linenum, args[1]);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
3649 free(curproxy->check_path);
3650 curproxy->check_path = strdup(args[2]);
3651 }
3652 else {
3653 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3654 file, linenum, args[1]);
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003659 else if (!strcmp(args[0], "persist")) { /* persist */
3660 if (*(args[1]) == 0) {
3661 Alert("parsing [%s:%d] : missing persist method.\n",
3662 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003665 }
3666
3667 if (!strncmp(args[1], "rdp-cookie", 10)) {
3668 curproxy->options2 |= PR_O2_RDPC_PRST;
3669
Emeric Brunb982a3d2010-01-04 15:45:53 +01003670 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003671 const char *beg, *end;
3672
3673 beg = args[1] + 11;
3674 end = strchr(beg, ')');
3675
William Lallemanddf1425a2015-04-28 20:17:49 +02003676 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3677 goto out;
3678
Emeric Brun647caf12009-06-30 17:57:00 +02003679 if (!end || end == beg) {
3680 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3681 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003684 }
3685
3686 free(curproxy->rdp_cookie_name);
3687 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3688 curproxy->rdp_cookie_len = end-beg;
3689 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003690 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003691 free(curproxy->rdp_cookie_name);
3692 curproxy->rdp_cookie_name = strdup("msts");
3693 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3694 }
3695 else { /* syntax */
3696 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3697 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003700 }
3701 }
3702 else {
3703 Alert("parsing [%s:%d] : unknown persist method.\n",
3704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003707 }
3708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003710 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003714 else if (!strcmp(args[0], "load-server-state-from-file")) {
3715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3716 err_code |= ERR_WARN;
3717 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3718 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3719 }
3720 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3721 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3722 }
3723 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3724 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3725 }
3726 else {
3727 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3728 file, linenum, args[0], args[1]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732 }
3733 else if (!strcmp(args[0], "server-state-file-name")) {
3734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3735 err_code |= ERR_WARN;
3736 if (*(args[1]) == 0) {
3737 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3738 file, linenum, args[0]);
3739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
3741 }
3742 else if (!strcmp(args[1], "use-backend-name"))
3743 curproxy->server_state_file_name = strdup(curproxy->id);
3744 else
3745 curproxy->server_state_file_name = strdup(args[1]);
3746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003748 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003752 if (curproxy == &defproxy) {
3753 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
3756 }
3757
William Lallemand1a748ae2015-05-19 16:37:23 +02003758 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3759 goto out;
3760
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 if (*(args[4]) == 0) {
3762 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3763 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003767 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 curproxy->capture_name = strdup(args[2]);
3769 curproxy->capture_namelen = strlen(curproxy->capture_name);
3770 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 curproxy->to_log |= LW_COOKIE;
3772 }
3773 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3774 struct cap_hdr *hdr;
3775
3776 if (curproxy == &defproxy) {
3777 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 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 }
3781
William Lallemand1a748ae2015-05-19 16:37:23 +02003782 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3783 goto out;
3784
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3786 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3787 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791
Vincent Bernat02779b62016-04-03 13:48:43 +02003792 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 hdr->next = curproxy->req_cap;
3794 hdr->name = strdup(args[3]);
3795 hdr->namelen = strlen(args[3]);
3796 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003797 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 hdr->index = curproxy->nb_req_cap++;
3799 curproxy->req_cap = hdr;
3800 curproxy->to_log |= LW_REQHDR;
3801 }
3802 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3803 struct cap_hdr *hdr;
3804
3805 if (curproxy == &defproxy) {
3806 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 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810
William Lallemand1a748ae2015-05-19 16:37:23 +02003811 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3812 goto out;
3813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3815 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3816 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003820 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 hdr->next = curproxy->rsp_cap;
3822 hdr->name = strdup(args[3]);
3823 hdr->namelen = strlen(args[3]);
3824 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003825 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 hdr->index = curproxy->nb_rsp_cap++;
3827 curproxy->rsp_cap = hdr;
3828 curproxy->to_log |= LW_RSPHDR;
3829 }
3830 else {
3831 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
3836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003840
William Lallemanddf1425a2015-04-28 20:17:49 +02003841 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3842 goto out;
3843
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 if (*(args[1]) == 0) {
3845 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3846 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
3850 curproxy->conn_retries = atol(args[1]);
3851 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003852 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003853 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003854
3855 if (curproxy == &defproxy) {
3856 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
3859 }
3860
Willy Tarreau20b0de52012-12-24 15:45:22 +01003861 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003862 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003863 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3864 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3865 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3866 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003867 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 +01003868 file, linenum, args[0]);
3869 err_code |= ERR_WARN;
3870 }
3871
Willy Tarreauff011f22011-01-06 17:51:27 +01003872 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003873
Willy Tarreauff011f22011-01-06 17:51:27 +01003874 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003875 err_code |= ERR_ALERT | ERR_ABORT;
3876 goto out;
3877 }
3878
Willy Tarreau5002f572014-04-23 01:32:02 +02003879 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003880 err_code |= warnif_cond_conflicts(rule->cond,
3881 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3882 file, linenum);
3883
Willy Tarreauff011f22011-01-06 17:51:27 +01003884 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003885 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003886 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003887 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003888
3889 if (curproxy == &defproxy) {
3890 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894
3895 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003896 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003897 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3898 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003899 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3900 file, linenum, args[0]);
3901 err_code |= ERR_WARN;
3902 }
3903
3904 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3905
3906 if (!rule) {
3907 err_code |= ERR_ALERT | ERR_ABORT;
3908 goto out;
3909 }
3910
3911 err_code |= warnif_cond_conflicts(rule->cond,
3912 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3913 file, linenum);
3914
3915 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3916 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003917 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3918 /* set the header name and length into the proxy structure */
3919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3920 err_code |= ERR_WARN;
3921
3922 if (!*args[1]) {
3923 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3924 file, linenum, args[0]);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928
3929 /* set the desired header name */
3930 free(curproxy->server_id_hdr_name);
3931 curproxy->server_id_hdr_name = strdup(args[1]);
3932 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3933 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003934 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003935 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003936
Willy Tarreaub099aca2008-10-12 17:26:37 +02003937 if (curproxy == &defproxy) {
3938 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003941 }
3942
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003943 /* emulate "block" using "http-request block". Since these rules are supposed to
3944 * be processed before all http-request rules, we put them into their own list
3945 * and will insert them at the end.
3946 */
3947 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3948 if (!rule) {
3949 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003950 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003951 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003952 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3953 err_code |= warnif_cond_conflicts(rule->cond,
3954 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3955 file, linenum);
3956 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003957
3958 if (!already_warned(WARN_BLOCK_DEPRECATED))
3959 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]);
3960
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003961 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003962 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003963 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003964
Cyril Bonté99ed3272010-01-24 23:29:44 +01003965 if (curproxy == &defproxy) {
3966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
3970
Willy Tarreaube4653b2015-05-28 15:26:58 +02003971 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003972 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3973 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003976 }
3977
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003978 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003979 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003980 err_code |= warnif_cond_conflicts(rule->cond,
3981 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3982 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003983 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003984 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003985 struct switching_rule *rule;
3986
Willy Tarreaub099aca2008-10-12 17:26:37 +02003987 if (curproxy == &defproxy) {
3988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003991 }
3992
Willy Tarreau55ea7572007-06-17 19:56:27 +02003993 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003995
3996 if (*(args[1]) == 0) {
3997 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004000 }
4001
Willy Tarreauf51658d2014-04-23 01:21:56 +02004002 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
4003 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4004 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4005 file, linenum, errmsg);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004009
Willy Tarreauf51658d2014-04-23 01:21:56 +02004010 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004011 }
4012
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004013 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02004014 rule->cond = cond;
4015 rule->be.name = strdup(args[1]);
4016 LIST_INIT(&rule->list);
4017 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4018 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004019 else if (strcmp(args[0], "use-server") == 0) {
4020 struct server_rule *rule;
4021
4022 if (curproxy == &defproxy) {
4023 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
4028 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4029 err_code |= ERR_WARN;
4030
4031 if (*(args[1]) == 0) {
4032 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
4037 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4038 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4039 file, linenum, args[0]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004044 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4045 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4046 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
4050
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004051 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004052
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004053 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004054 rule->cond = cond;
4055 rule->srv.name = strdup(args[1]);
4056 LIST_INIT(&rule->list);
4057 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4058 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4059 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004060 else if ((!strcmp(args[0], "force-persist")) ||
4061 (!strcmp(args[0], "ignore-persist"))) {
4062 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004063
4064 if (curproxy == &defproxy) {
4065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
4070 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4071 err_code |= ERR_WARN;
4072
Willy Tarreauef6494c2010-01-28 17:12:36 +01004073 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004074 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4075 file, linenum, args[0]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004080 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4081 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4082 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004087 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4088 * where force-persist is applied.
4089 */
4090 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004091
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004092 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004093 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004094 if (!strcmp(args[0], "force-persist")) {
4095 rule->type = PERSIST_TYPE_FORCE;
4096 } else {
4097 rule->type = PERSIST_TYPE_IGNORE;
4098 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004099 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004100 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004101 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004102 else if (!strcmp(args[0], "stick-table")) {
4103 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004104 struct proxy *other;
4105
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004106 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004107 if (other) {
4108 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4109 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113
Emeric Brun32da3c42010-09-23 18:39:19 +02004114 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004115 curproxy->table.type = (unsigned int)-1;
4116 while (*args[myidx]) {
4117 const char *err;
4118
4119 if (strcmp(args[myidx], "size") == 0) {
4120 myidx++;
4121 if (!*(args[myidx])) {
4122 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4123 file, linenum, args[myidx-1]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4128 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4129 file, linenum, *err, args[myidx-1]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004133 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004134 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004135 else if (strcmp(args[myidx], "peers") == 0) {
4136 myidx++;
Godbach50523162013-12-11 19:48:57 +08004137 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004138 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4139 file, linenum, args[myidx-1]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Godbach50523162013-12-11 19:48:57 +08004142 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004143 curproxy->table.peers.name = strdup(args[myidx++]);
4144 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 else if (strcmp(args[myidx], "expire") == 0) {
4146 myidx++;
4147 if (!*(args[myidx])) {
4148 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4149 file, linenum, args[myidx-1]);
4150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
4152 }
4153 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4154 if (err) {
4155 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4156 file, linenum, *err, args[myidx-1]);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004160 if (val > INT_MAX) {
4161 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4162 file, linenum, val);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004166 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004167 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004168 }
4169 else if (strcmp(args[myidx], "nopurge") == 0) {
4170 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004171 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004172 }
4173 else if (strcmp(args[myidx], "type") == 0) {
4174 myidx++;
4175 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4176 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4177 file, linenum, args[myidx]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004181 /* myidx already points to next arg */
4182 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004183 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004184 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004185 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004186
4187 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004188 nw = args[myidx];
4189 while (*nw) {
4190 /* the "store" keyword supports a comma-separated list */
4191 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004192 sa = NULL; /* store arg */
4193 while (*nw && *nw != ',') {
4194 if (*nw == '(') {
4195 *nw = 0;
4196 sa = ++nw;
4197 while (*nw != ')') {
4198 if (!*nw) {
4199 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4200 file, linenum, args[0], cw);
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
4204 nw++;
4205 }
4206 *nw = '\0';
4207 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004208 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004209 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004210 if (*nw)
4211 *nw++ = '\0';
4212 type = stktable_get_data_type(cw);
4213 if (type < 0) {
4214 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4215 file, linenum, args[0], cw);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 }
Willy Tarreauac782882010-06-20 10:41:54 +02004219
4220 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4221 switch (err) {
4222 case PE_NONE: break;
4223 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004224 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4225 file, linenum, args[0], cw);
4226 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004227 break;
4228
4229 case PE_ARG_MISSING:
4230 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4231 file, linenum, args[0], cw);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234
4235 case PE_ARG_NOT_USED:
4236 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4237 file, linenum, args[0], cw);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240
4241 default:
4242 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4243 file, linenum, args[0], cw);
4244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004246 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004247 }
4248 myidx++;
4249 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004250 else {
4251 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4252 file, linenum, args[myidx]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004255 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004256 }
4257
4258 if (!curproxy->table.size) {
4259 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4260 file, linenum);
4261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
4264
4265 if (curproxy->table.type == (unsigned int)-1) {
4266 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4267 file, linenum);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271 }
4272 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004273 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004274 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004275 int myidx = 0;
4276 const char *name = NULL;
4277 int flags;
4278
4279 if (curproxy == &defproxy) {
4280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
4283 }
4284
4285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4286 err_code |= ERR_WARN;
4287 goto out;
4288 }
4289
4290 myidx++;
4291 if ((strcmp(args[myidx], "store") == 0) ||
4292 (strcmp(args[myidx], "store-request") == 0)) {
4293 myidx++;
4294 flags = STK_IS_STORE;
4295 }
4296 else if (strcmp(args[myidx], "store-response") == 0) {
4297 myidx++;
4298 flags = STK_IS_STORE | STK_ON_RSP;
4299 }
4300 else if (strcmp(args[myidx], "match") == 0) {
4301 myidx++;
4302 flags = STK_IS_MATCH;
4303 }
4304 else if (strcmp(args[myidx], "on") == 0) {
4305 myidx++;
4306 flags = STK_IS_MATCH | STK_IS_STORE;
4307 }
4308 else {
4309 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
4314 if (*(args[myidx]) == 0) {
4315 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004320 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004321 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004322 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004323 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327
4328 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004329 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4330 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4331 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004332 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004333 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004334 goto out;
4335 }
4336 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004337 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4338 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4339 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004340 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004341 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004342 goto out;
4343 }
4344 }
4345
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004346 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004347 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004348
Emeric Brunb982a3d2010-01-04 15:45:53 +01004349 if (strcmp(args[myidx], "table") == 0) {
4350 myidx++;
4351 name = args[myidx++];
4352 }
4353
Willy Tarreauef6494c2010-01-28 17:12:36 +01004354 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004355 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4356 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4357 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004358 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004359 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004360 goto out;
4361 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004362 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004363 else if (*(args[myidx])) {
4364 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4365 file, linenum, args[0], args[myidx]);
4366 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004367 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004368 goto out;
4369 }
Emeric Brun97679e72010-09-23 17:56:44 +02004370 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004371 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004372 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004373 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004374
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004375 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004376 rule->cond = cond;
4377 rule->expr = expr;
4378 rule->flags = flags;
4379 rule->table.name = name ? strdup(name) : NULL;
4380 LIST_INIT(&rule->list);
4381 if (flags & STK_ON_RSP)
4382 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4383 else
4384 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 else if (!strcmp(args[0], "stats")) {
4387 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4388 curproxy->uri_auth = NULL; /* we must detach from the default config */
4389
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004390 if (!*args[1]) {
4391 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004392 } else if (!strcmp(args[1], "admin")) {
4393 struct stats_admin_rule *rule;
4394
4395 if (curproxy == &defproxy) {
4396 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400
4401 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4403 err_code |= ERR_ALERT | ERR_ABORT;
4404 goto out;
4405 }
4406
4407 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4408 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4409 file, linenum, args[0], args[1]);
4410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004413 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4414 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4415 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
4418 }
4419
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004420 err_code |= warnif_cond_conflicts(cond,
4421 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4422 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004423
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004424 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004425 rule->cond = cond;
4426 LIST_INIT(&rule->list);
4427 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 } else if (!strcmp(args[1], "uri")) {
4429 if (*(args[2]) == 0) {
4430 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4434 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_ABORT;
4436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 }
4438 } else if (!strcmp(args[1], "realm")) {
4439 if (*(args[2]) == 0) {
4440 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4444 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_ABORT;
4446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004448 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004449 unsigned interval;
4450
4451 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4452 if (err) {
4453 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4454 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004457 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4458 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_ABORT;
4460 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004461 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004462 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004463 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004464
4465 if (curproxy == &defproxy) {
4466 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
4470
4471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4472 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4473 err_code |= ERR_ALERT | ERR_ABORT;
4474 goto out;
4475 }
4476
Willy Tarreauff011f22011-01-06 17:51:27 +01004477 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004478 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004479 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4480 file, linenum, args[0]);
4481 err_code |= ERR_WARN;
4482 }
4483
Willy Tarreauff011f22011-01-06 17:51:27 +01004484 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004485
Willy Tarreauff011f22011-01-06 17:51:27 +01004486 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
4489 }
4490
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004491 err_code |= warnif_cond_conflicts(rule->cond,
4492 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4493 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004494 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004495
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 } else if (!strcmp(args[1], "auth")) {
4497 if (*(args[2]) == 0) {
4498 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4502 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_ABORT;
4504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
4506 } else if (!strcmp(args[1], "scope")) {
4507 if (*(args[2]) == 0) {
4508 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4512 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_ALERT | ERR_ABORT;
4514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 }
4516 } else if (!strcmp(args[1], "enable")) {
4517 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4518 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_ABORT;
4520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004522 } else if (!strcmp(args[1], "hide-version")) {
4523 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4524 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_ABORT;
4526 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004527 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004528 } else if (!strcmp(args[1], "show-legends")) {
4529 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4530 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4531 err_code |= ERR_ALERT | ERR_ABORT;
4532 goto out;
4533 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004534 } else if (!strcmp(args[1], "show-node")) {
4535
4536 if (*args[2]) {
4537 int i;
4538 char c;
4539
4540 for (i=0; args[2][i]; i++) {
4541 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004542 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4543 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004544 break;
4545 }
4546
4547 if (!i || args[2][i]) {
4548 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4549 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4550 file, linenum, args[0], args[1]);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
4554 }
4555
4556 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4557 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4558 err_code |= ERR_ALERT | ERR_ABORT;
4559 goto out;
4560 }
4561 } else if (!strcmp(args[1], "show-desc")) {
4562 char *desc = NULL;
4563
4564 if (*args[2]) {
4565 int i, len=0;
4566 char *d;
4567
Willy Tarreau348acfe2014-04-14 15:00:39 +02004568 for (i = 2; *args[i]; i++)
4569 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004570
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004571 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004572
Willy Tarreau348acfe2014-04-14 15:00:39 +02004573 d += snprintf(d, desc + len - d, "%s", args[2]);
4574 for (i = 3; *args[i]; i++)
4575 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004576 }
4577
4578 if (!*args[2] && !global.desc)
4579 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4580 file, linenum, args[1]);
4581 else {
4582 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4583 free(desc);
4584 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4585 err_code |= ERR_ALERT | ERR_ABORT;
4586 goto out;
4587 }
4588 free(desc);
4589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004591stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004592 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 +01004593 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
4597 }
4598 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004599 int optnum;
4600
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004601 if (*(args[1]) == '\0') {
4602 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004607
4608 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4609 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004610 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4611 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4612 file, linenum, cfg_opts[optnum].name);
4613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
4615 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004616 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4617 goto out;
4618
Willy Tarreau93893792009-07-23 13:19:11 +02004619 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4620 err_code |= ERR_WARN;
4621 goto out;
4622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004623
Willy Tarreau3842f002009-06-14 11:39:52 +02004624 curproxy->no_options &= ~cfg_opts[optnum].val;
4625 curproxy->options &= ~cfg_opts[optnum].val;
4626
4627 switch (kwm) {
4628 case KWM_STD:
4629 curproxy->options |= cfg_opts[optnum].val;
4630 break;
4631 case KWM_NO:
4632 curproxy->no_options |= cfg_opts[optnum].val;
4633 break;
4634 case KWM_DEF: /* already cleared */
4635 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004636 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004637
Willy Tarreau93893792009-07-23 13:19:11 +02004638 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004639 }
4640 }
4641
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004642 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4643 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004644 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4645 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4646 file, linenum, cfg_opts2[optnum].name);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004650 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4651 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004652 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4653 err_code |= ERR_WARN;
4654 goto out;
4655 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004656
Willy Tarreau3842f002009-06-14 11:39:52 +02004657 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4658 curproxy->options2 &= ~cfg_opts2[optnum].val;
4659
4660 switch (kwm) {
4661 case KWM_STD:
4662 curproxy->options2 |= cfg_opts2[optnum].val;
4663 break;
4664 case KWM_NO:
4665 curproxy->no_options2 |= cfg_opts2[optnum].val;
4666 break;
4667 case KWM_DEF: /* already cleared */
4668 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004669 }
Willy Tarreau93893792009-07-23 13:19:11 +02004670 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004671 }
4672 }
4673
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004674 /* HTTP options override each other. They can be cancelled using
4675 * "no option xxx" which only switches to default mode if the mode
4676 * was this one (useful for cancelling options set in defaults
4677 * sections).
4678 */
4679 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4681 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004682 if (kwm == KWM_STD) {
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 curproxy->options |= PR_O_HTTP_PCL;
4685 goto out;
4686 }
4687 else if (kwm == KWM_NO) {
4688 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4689 curproxy->options &= ~PR_O_HTTP_MODE;
4690 goto out;
4691 }
4692 }
4693 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004694 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4695 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004696 if (kwm == KWM_STD) {
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 curproxy->options |= PR_O_HTTP_FCL;
4699 goto out;
4700 }
4701 else if (kwm == KWM_NO) {
4702 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4703 curproxy->options &= ~PR_O_HTTP_MODE;
4704 goto out;
4705 }
4706 }
4707 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004708 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4709 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004710 if (kwm == KWM_STD) {
4711 curproxy->options &= ~PR_O_HTTP_MODE;
4712 curproxy->options |= PR_O_HTTP_SCL;
4713 goto out;
4714 }
4715 else if (kwm == KWM_NO) {
4716 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4717 curproxy->options &= ~PR_O_HTTP_MODE;
4718 goto out;
4719 }
4720 }
4721 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004722 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4723 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004724 if (kwm == KWM_STD) {
4725 curproxy->options &= ~PR_O_HTTP_MODE;
4726 curproxy->options |= PR_O_HTTP_KAL;
4727 goto out;
4728 }
4729 else if (kwm == KWM_NO) {
4730 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4731 curproxy->options &= ~PR_O_HTTP_MODE;
4732 goto out;
4733 }
4734 }
4735 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004736 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4737 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004738 if (kwm == KWM_STD) {
4739 curproxy->options &= ~PR_O_HTTP_MODE;
4740 curproxy->options |= PR_O_HTTP_TUN;
4741 goto out;
4742 }
4743 else if (kwm == KWM_NO) {
4744 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4745 curproxy->options &= ~PR_O_HTTP_MODE;
4746 goto out;
4747 }
4748 }
4749
Joseph Lynch726ab712015-05-11 23:25:34 -07004750 /* Redispatch can take an integer argument that control when the
4751 * resispatch occurs. All values are relative to the retries option.
4752 * This can be cancelled using "no option xxx".
4753 */
4754 if (strcmp(args[1], "redispatch") == 0) {
4755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4756 err_code |= ERR_WARN;
4757 goto out;
4758 }
4759
4760 curproxy->no_options &= ~PR_O_REDISP;
4761 curproxy->options &= ~PR_O_REDISP;
4762
4763 switch (kwm) {
4764 case KWM_STD:
4765 curproxy->options |= PR_O_REDISP;
4766 curproxy->redispatch_after = -1;
4767 if(*args[2]) {
4768 curproxy->redispatch_after = atol(args[2]);
4769 }
4770 break;
4771 case KWM_NO:
4772 curproxy->no_options |= PR_O_REDISP;
4773 curproxy->redispatch_after = 0;
4774 break;
4775 case KWM_DEF: /* already cleared */
4776 break;
4777 }
4778 goto out;
4779 }
4780
Willy Tarreau3842f002009-06-14 11:39:52 +02004781 if (kwm != KWM_STD) {
4782 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004783 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004786 }
4787
Emeric Brun3a058f32009-06-30 18:26:00 +02004788 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004789 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004791 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004792 if (*(args[2]) != '\0') {
4793 if (!strcmp(args[2], "clf")) {
4794 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004795 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004796 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004797 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004800 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004801 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4802 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004803 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004804 if (curproxy->conf.logformat_string != default_http_log_format &&
4805 curproxy->conf.logformat_string != default_tcp_log_format &&
4806 curproxy->conf.logformat_string != clf_http_log_format)
4807 free(curproxy->conf.logformat_string);
4808 curproxy->conf.logformat_string = logformat;
4809
4810 free(curproxy->conf.lfs_file);
4811 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4812 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004813 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004814 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004816 if (curproxy->conf.logformat_string != default_http_log_format &&
4817 curproxy->conf.logformat_string != default_tcp_log_format &&
4818 curproxy->conf.logformat_string != clf_http_log_format)
4819 free(curproxy->conf.logformat_string);
4820 curproxy->conf.logformat_string = default_tcp_log_format;
4821
4822 free(curproxy->conf.lfs_file);
4823 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4824 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004825
4826 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4827 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004830 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004831 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004833
William Lallemanddf1425a2015-04-28 20:17:49 +02004834 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4835 goto out;
4836
Willy Tarreau13943ab2006-12-31 00:24:10 +01004837 if (curproxy->cap & PR_CAP_FE)
4838 curproxy->options |= PR_O_TCP_CLI_KA;
4839 if (curproxy->cap & PR_CAP_BE)
4840 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
4842 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_WARN;
4845
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004847 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004848 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004849 curproxy->options2 &= ~PR_O2_CHK_ANY;
4850 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 if (!*args[2]) { /* no argument */
4852 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4853 curproxy->check_len = strlen(DEF_CHECK_REQ);
4854 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004855 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004856 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004858 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004860 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 if (*args[4])
4862 reqlen += strlen(args[4]);
4863 else
4864 reqlen += strlen("HTTP/1.0");
4865
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004866 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004868 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004870 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4871 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004872 }
4873 else if (!strcmp(args[1], "ssl-hello-chk")) {
4874 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004877
Willy Tarreaua534fea2008-08-03 12:19:50 +02004878 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004879 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004880 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004881 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004882
4883 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
Willy Tarreau23677902007-05-08 23:50:35 +02004886 else if (!strcmp(args[1], "smtpchk")) {
4887 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004888 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004889 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004890 curproxy->options2 &= ~PR_O2_CHK_ANY;
4891 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004892
4893 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4894 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4895 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4896 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4897 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4898 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004899 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004900 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4901 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4902 } else {
4903 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4904 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4905 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4906 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4907 }
4908 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004909 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4910 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004911 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004912 else if (!strcmp(args[1], "pgsql-check")) {
4913 /* use PostgreSQL request to check servers' health */
4914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4915 err_code |= ERR_WARN;
4916
4917 free(curproxy->check_req);
4918 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004919 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004920 curproxy->options2 |= PR_O2_PGSQL_CHK;
4921
4922 if (*(args[2])) {
4923 int cur_arg = 2;
4924
4925 while (*(args[cur_arg])) {
4926 if (strcmp(args[cur_arg], "user") == 0) {
4927 char * packet;
4928 uint32_t packet_len;
4929 uint32_t pv;
4930
4931 /* suboption header - needs additional argument for it */
4932 if (*(args[cur_arg+1]) == 0) {
4933 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4934 file, linenum, args[0], args[1], args[cur_arg]);
4935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
4937 }
4938
4939 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4940 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4941 pv = htonl(0x30000); /* protocol version 3.0 */
4942
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004943 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004944
4945 memcpy(packet + 4, &pv, 4);
4946
4947 /* copy "user" */
4948 memcpy(packet + 8, "user", 4);
4949
4950 /* copy username */
4951 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4952
4953 free(curproxy->check_req);
4954 curproxy->check_req = packet;
4955 curproxy->check_len = packet_len;
4956
4957 packet_len = htonl(packet_len);
4958 memcpy(packet, &packet_len, 4);
4959 cur_arg += 2;
4960 } else {
4961 /* unknown suboption - catchall */
4962 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4963 file, linenum, args[0], args[1]);
4964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
4966 }
4967 } /* end while loop */
4968 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004969 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4970 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004971 }
4972
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004973 else if (!strcmp(args[1], "redis-check")) {
4974 /* use REDIS PING request to check servers' health */
4975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4976 err_code |= ERR_WARN;
4977
4978 free(curproxy->check_req);
4979 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004980 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004981 curproxy->options2 |= PR_O2_REDIS_CHK;
4982
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004983 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004984 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4985 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004986
4987 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4988 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004989 }
4990
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004991 else if (!strcmp(args[1], "mysql-check")) {
4992 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4994 err_code |= ERR_WARN;
4995
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004996 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004997 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004998 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004999 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005000
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005001 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005002 * const char mysql40_client_auth_pkt[] = {
5003 * "\x0e\x00\x00" // packet length
5004 * "\x01" // packet number
5005 * "\x00\x00" // client capabilities
5006 * "\x00\x00\x01" // max packet
5007 * "haproxy\x00" // username (null terminated string)
5008 * "\x00" // filler (always 0x00)
5009 * "\x01\x00\x00" // packet length
5010 * "\x00" // packet number
5011 * "\x01" // COM_QUIT command
5012 * };
5013 */
5014
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005015 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5016 * const char mysql41_client_auth_pkt[] = {
5017 * "\x0e\x00\x00\" // packet length
5018 * "\x01" // packet number
5019 * "\x00\x00\x00\x00" // client capabilities
5020 * "\x00\x00\x00\x01" // max packet
5021 * "\x21" // character set (UTF-8)
5022 * char[23] // All zeroes
5023 * "haproxy\x00" // username (null terminated string)
5024 * "\x00" // filler (always 0x00)
5025 * "\x01\x00\x00" // packet length
5026 * "\x00" // packet number
5027 * "\x01" // COM_QUIT command
5028 * };
5029 */
5030
5031
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005032 if (*(args[2])) {
5033 int cur_arg = 2;
5034
5035 while (*(args[cur_arg])) {
5036 if (strcmp(args[cur_arg], "user") == 0) {
5037 char *mysqluser;
5038 int packetlen, reqlen, userlen;
5039
5040 /* suboption header - needs additional argument for it */
5041 if (*(args[cur_arg+1]) == 0) {
5042 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5043 file, linenum, args[0], args[1], args[cur_arg]);
5044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
5046 }
5047 mysqluser = args[cur_arg + 1];
5048 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005049
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005050 if (*(args[cur_arg+2])) {
5051 if (!strcmp(args[cur_arg+2], "post-41")) {
5052 packetlen = userlen + 7 + 27;
5053 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005054
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005055 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005056 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005057 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005058
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005059 snprintf(curproxy->check_req, 4, "%c%c%c",
5060 ((unsigned char) packetlen & 0xff),
5061 ((unsigned char) (packetlen >> 8) & 0xff),
5062 ((unsigned char) (packetlen >> 16) & 0xff));
5063
5064 curproxy->check_req[3] = 1;
5065 curproxy->check_req[5] = 130;
5066 curproxy->check_req[11] = 1;
5067 curproxy->check_req[12] = 33;
5068 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5069 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5070 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5071 cur_arg += 3;
5072 } else {
5073 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
5077 } else {
5078 packetlen = userlen + 7;
5079 reqlen = packetlen + 9;
5080
5081 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005082 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005083 curproxy->check_len = reqlen;
5084
5085 snprintf(curproxy->check_req, 4, "%c%c%c",
5086 ((unsigned char) packetlen & 0xff),
5087 ((unsigned char) (packetlen >> 8) & 0xff),
5088 ((unsigned char) (packetlen >> 16) & 0xff));
5089
5090 curproxy->check_req[3] = 1;
5091 curproxy->check_req[5] = 128;
5092 curproxy->check_req[8] = 1;
5093 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5094 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5095 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5096 cur_arg += 2;
5097 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005098 } else {
5099 /* unknown suboption - catchall */
5100 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5101 file, linenum, args[0], args[1]);
5102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
5104 }
5105 } /* end while loop */
5106 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005107 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005108 else if (!strcmp(args[1], "ldap-check")) {
5109 /* use LDAP request to check servers' health */
5110 free(curproxy->check_req);
5111 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005112 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005113 curproxy->options2 |= PR_O2_LDAP_CHK;
5114
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005115 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005116 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5117 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005118 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5119 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005120 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005121 else if (!strcmp(args[1], "tcp-check")) {
5122 /* use raw TCPCHK send/expect to check servers' health */
5123 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5124 err_code |= ERR_WARN;
5125
5126 free(curproxy->check_req);
5127 curproxy->check_req = NULL;
5128 curproxy->options2 &= ~PR_O2_CHK_ANY;
5129 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005130 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5131 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005132 }
Simon Horman98637e52014-06-20 12:30:16 +09005133 else if (!strcmp(args[1], "external-check")) {
5134 /* excute an external command to check servers' health */
5135 free(curproxy->check_req);
5136 curproxy->check_req = NULL;
5137 curproxy->options2 &= ~PR_O2_CHK_ANY;
5138 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005139 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5140 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005141 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005142 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005143 int cur_arg;
5144
5145 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5146 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005147 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005148
Willy Tarreau87cf5142011-08-19 22:57:24 +02005149 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005150
5151 free(curproxy->fwdfor_hdr_name);
5152 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5153 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5154
5155 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5156 cur_arg = 2;
5157 while (*(args[cur_arg])) {
5158 if (!strcmp(args[cur_arg], "except")) {
5159 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005160 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005161 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5162 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005165 }
5166 /* flush useless bits */
5167 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005168 cur_arg += 2;
5169 } else if (!strcmp(args[cur_arg], "header")) {
5170 /* suboption header - needs additional argument for it */
5171 if (*(args[cur_arg+1]) == 0) {
5172 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5173 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005176 }
5177 free(curproxy->fwdfor_hdr_name);
5178 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5179 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5180 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005181 } else if (!strcmp(args[cur_arg], "if-none")) {
5182 curproxy->options &= ~PR_O_FF_ALWAYS;
5183 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005184 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005185 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005186 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005187 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005190 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005191 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005192 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005193 else if (!strcmp(args[1], "originalto")) {
5194 int cur_arg;
5195
5196 /* insert x-original-to field, but not for the IP address listed as an except.
5197 * set default options (ie: bitfield, header name, etc)
5198 */
5199
5200 curproxy->options |= PR_O_ORGTO;
5201
5202 free(curproxy->orgto_hdr_name);
5203 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5204 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5205
Willy Tarreau87cf5142011-08-19 22:57:24 +02005206 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005207 cur_arg = 2;
5208 while (*(args[cur_arg])) {
5209 if (!strcmp(args[cur_arg], "except")) {
5210 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005211 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 +02005212 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5213 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005216 }
5217 /* flush useless bits */
5218 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5219 cur_arg += 2;
5220 } else if (!strcmp(args[cur_arg], "header")) {
5221 /* suboption header - needs additional argument for it */
5222 if (*(args[cur_arg+1]) == 0) {
5223 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5224 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005227 }
5228 free(curproxy->orgto_hdr_name);
5229 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5230 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5231 cur_arg += 2;
5232 } else {
5233 /* unknown suboption - catchall */
5234 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5235 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005238 }
5239 } /* end while loop */
5240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 else {
5242 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245 }
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005248 else if (!strcmp(args[0], "default_backend")) {
5249 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005251
5252 if (*(args[1]) == 0) {
5253 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005256 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005257 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005258 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005259
5260 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5261 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005266
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005267 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5268 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 +01005269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 /* enable reconnections to dispatch */
5272 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005273
5274 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005277 else if (!strcmp(args[0], "http-reuse")) {
5278 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5279 err_code |= ERR_WARN;
5280
5281 if (strcmp(args[1], "never") == 0) {
5282 /* enable a graceful server shutdown on an HTTP 404 response */
5283 curproxy->options &= ~PR_O_REUSE_MASK;
5284 curproxy->options |= PR_O_REUSE_NEVR;
5285 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5286 goto out;
5287 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005288 else if (strcmp(args[1], "safe") == 0) {
5289 /* enable a graceful server shutdown on an HTTP 404 response */
5290 curproxy->options &= ~PR_O_REUSE_MASK;
5291 curproxy->options |= PR_O_REUSE_SAFE;
5292 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5293 goto out;
5294 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005295 else if (strcmp(args[1], "aggressive") == 0) {
5296 curproxy->options &= ~PR_O_REUSE_MASK;
5297 curproxy->options |= PR_O_REUSE_AGGR;
5298 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5299 goto out;
5300 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005301 else if (strcmp(args[1], "always") == 0) {
5302 /* enable a graceful server shutdown on an HTTP 404 response */
5303 curproxy->options &= ~PR_O_REUSE_MASK;
5304 curproxy->options |= PR_O_REUSE_ALWS;
5305 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5306 goto out;
5307 }
5308 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005309 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005314 else if (!strcmp(args[0], "http-check")) {
5315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005317
5318 if (strcmp(args[1], "disable-on-404") == 0) {
5319 /* enable a graceful server shutdown on an HTTP 404 response */
5320 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005321 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5322 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005323 }
Willy Tarreauef781042010-01-27 11:53:01 +01005324 else if (strcmp(args[1], "send-state") == 0) {
5325 /* enable emission of the apparent state of a server in HTTP checks */
5326 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005327 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5328 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005329 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005330 else if (strcmp(args[1], "expect") == 0) {
5331 const char *ptr_arg;
5332 int cur_arg;
5333
5334 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5335 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339
5340 cur_arg = 2;
5341 /* consider exclamation marks, sole or at the beginning of a word */
5342 while (*(ptr_arg = args[cur_arg])) {
5343 while (*ptr_arg == '!') {
5344 curproxy->options2 ^= PR_O2_EXP_INV;
5345 ptr_arg++;
5346 }
5347 if (*ptr_arg)
5348 break;
5349 cur_arg++;
5350 }
5351 /* now ptr_arg points to the beginning of a word past any possible
5352 * exclamation mark, and cur_arg is the argument which holds this word.
5353 */
5354 if (strcmp(ptr_arg, "status") == 0) {
5355 if (!*(args[cur_arg + 1])) {
5356 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5357 file, linenum, args[0], args[1], ptr_arg);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005362 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005363 curproxy->expect_str = strdup(args[cur_arg + 1]);
5364 }
5365 else if (strcmp(ptr_arg, "string") == 0) {
5366 if (!*(args[cur_arg + 1])) {
5367 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5368 file, linenum, args[0], args[1], ptr_arg);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005373 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005374 curproxy->expect_str = strdup(args[cur_arg + 1]);
5375 }
5376 else if (strcmp(ptr_arg, "rstatus") == 0) {
5377 if (!*(args[cur_arg + 1])) {
5378 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5379 file, linenum, args[0], args[1], ptr_arg);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005384 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005385 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005386 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005387 free(curproxy->expect_regex);
5388 curproxy->expect_regex = NULL;
5389 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005390 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005391 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5392 error = NULL;
5393 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5394 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5395 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5396 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400 }
5401 else if (strcmp(ptr_arg, "rstring") == 0) {
5402 if (!*(args[cur_arg + 1])) {
5403 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5404 file, linenum, args[0], args[1], ptr_arg);
5405 err_code |= ERR_ALERT | ERR_FATAL;
5406 goto out;
5407 }
5408 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005409 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005410 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005411 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005412 free(curproxy->expect_regex);
5413 curproxy->expect_regex = NULL;
5414 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005415 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005416 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5417 error = NULL;
5418 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5419 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5420 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5421 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425 }
5426 else {
5427 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5428 file, linenum, args[0], args[1], ptr_arg);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005433 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005434 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 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005437 }
5438 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005439 else if (!strcmp(args[0], "tcp-check")) {
5440 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5441 err_code |= ERR_WARN;
5442
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005443 if (strcmp(args[1], "comment") == 0) {
5444 int cur_arg;
5445 struct tcpcheck_rule *tcpcheck;
5446
5447 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005448 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005449 tcpcheck->action = TCPCHK_ACT_COMMENT;
5450
5451 if (!*args[cur_arg + 1]) {
5452 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5453 file, linenum, args[cur_arg]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457
5458 tcpcheck->comment = strdup(args[cur_arg + 1]);
5459
5460 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005461 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5462 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005463 }
5464 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005465 const char *ptr_arg;
5466 int cur_arg;
5467 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005468
5469 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005470 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5471 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5472 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5473 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5474 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005475
Willy Tarreau5581c272015-05-13 12:24:53 +02005476 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5477 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5478 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5479 file, linenum);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005482 }
5483
5484 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005485 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005486 tcpcheck->action = TCPCHK_ACT_CONNECT;
5487
5488 /* parsing each parameters to fill up the rule */
5489 while (*(ptr_arg = args[cur_arg])) {
5490 /* tcp port */
5491 if (strcmp(args[cur_arg], "port") == 0) {
5492 if ( (atol(args[cur_arg + 1]) > 65535) ||
5493 (atol(args[cur_arg + 1]) < 1) ){
5494 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5495 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499 tcpcheck->port = atol(args[cur_arg + 1]);
5500 cur_arg += 2;
5501 }
5502 /* send proxy protocol */
5503 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5504 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5505 cur_arg++;
5506 }
5507#ifdef USE_OPENSSL
5508 else if (strcmp(args[cur_arg], "ssl") == 0) {
5509 curproxy->options |= PR_O_TCPCHK_SSL;
5510 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5511 cur_arg++;
5512 }
5513#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005514 /* comment for this tcpcheck line */
5515 else if (strcmp(args[cur_arg], "comment") == 0) {
5516 if (!*args[cur_arg + 1]) {
5517 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5518 file, linenum, args[cur_arg]);
5519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
5521 }
5522 tcpcheck->comment = strdup(args[cur_arg + 1]);
5523 cur_arg += 2;
5524 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005525 else {
5526#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005527 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 +01005528#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005529 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 +01005530#endif /* USE_OPENSSL */
5531 file, linenum, args[0], args[1], args[cur_arg]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535
5536 }
5537
5538 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5539 }
5540 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541 if (! *(args[2]) ) {
5542 /* SEND string expected */
5543 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5544 file, linenum, args[0], args[1], args[2]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 } else {
5548 struct tcpcheck_rule *tcpcheck;
5549
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005550 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005551
5552 tcpcheck->action = TCPCHK_ACT_SEND;
5553 tcpcheck->string_len = strlen(args[2]);
5554 tcpcheck->string = strdup(args[2]);
5555 tcpcheck->expect_regex = NULL;
5556
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005557 /* comment for this tcpcheck line */
5558 if (strcmp(args[3], "comment") == 0) {
5559 if (!*args[4]) {
5560 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5561 file, linenum, args[3]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565 tcpcheck->comment = strdup(args[4]);
5566 }
5567
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5569 }
5570 }
5571 else if (strcmp(args[1], "send-binary") == 0) {
5572 if (! *(args[2]) ) {
5573 /* SEND binary string expected */
5574 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5575 file, linenum, args[0], args[1], args[2]);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 } else {
5579 struct tcpcheck_rule *tcpcheck;
5580 char *err = NULL;
5581
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005582 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005583
5584 tcpcheck->action = TCPCHK_ACT_SEND;
5585 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5586 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5587 file, linenum, args[0], args[1], args[2], err);
5588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
5590 }
5591 tcpcheck->expect_regex = NULL;
5592
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005593 /* comment for this tcpcheck line */
5594 if (strcmp(args[3], "comment") == 0) {
5595 if (!*args[4]) {
5596 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5597 file, linenum, args[3]);
5598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
5600 }
5601 tcpcheck->comment = strdup(args[4]);
5602 }
5603
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005604 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5605 }
5606 }
5607 else if (strcmp(args[1], "expect") == 0) {
5608 const char *ptr_arg;
5609 int cur_arg;
5610 int inverse = 0;
5611
5612 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5613 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617
5618 cur_arg = 2;
5619 /* consider exclamation marks, sole or at the beginning of a word */
5620 while (*(ptr_arg = args[cur_arg])) {
5621 while (*ptr_arg == '!') {
5622 inverse = !inverse;
5623 ptr_arg++;
5624 }
5625 if (*ptr_arg)
5626 break;
5627 cur_arg++;
5628 }
5629 /* now ptr_arg points to the beginning of a word past any possible
5630 * exclamation mark, and cur_arg is the argument which holds this word.
5631 */
5632 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005633 struct tcpcheck_rule *tcpcheck;
5634 char *err = NULL;
5635
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005636 if (!*(args[cur_arg + 1])) {
5637 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5638 file, linenum, args[0], args[1], ptr_arg);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005642
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005643 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005644
5645 tcpcheck->action = TCPCHK_ACT_EXPECT;
5646 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5647 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5648 file, linenum, args[0], args[1], args[2], err);
5649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
5651 }
5652 tcpcheck->expect_regex = NULL;
5653 tcpcheck->inverse = inverse;
5654
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005655 /* tcpcheck comment */
5656 cur_arg += 2;
5657 if (strcmp(args[cur_arg], "comment") == 0) {
5658 if (!*args[cur_arg + 1]) {
5659 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5660 file, linenum, args[cur_arg + 1]);
5661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664 tcpcheck->comment = strdup(args[cur_arg + 1]);
5665 }
5666
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005667 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5668 }
5669 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005670 struct tcpcheck_rule *tcpcheck;
5671
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005672 if (!*(args[cur_arg + 1])) {
5673 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5674 file, linenum, args[0], args[1], ptr_arg);
5675 err_code |= ERR_ALERT | ERR_FATAL;
5676 goto out;
5677 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005678
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005679 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005680
5681 tcpcheck->action = TCPCHK_ACT_EXPECT;
5682 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5683 tcpcheck->string = strdup(args[cur_arg + 1]);
5684 tcpcheck->expect_regex = NULL;
5685 tcpcheck->inverse = inverse;
5686
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005687 /* tcpcheck comment */
5688 cur_arg += 2;
5689 if (strcmp(args[cur_arg], "comment") == 0) {
5690 if (!*args[cur_arg + 1]) {
5691 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5692 file, linenum, args[cur_arg + 1]);
5693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
5695 }
5696 tcpcheck->comment = strdup(args[cur_arg + 1]);
5697 }
5698
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005699 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5700 }
5701 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005702 struct tcpcheck_rule *tcpcheck;
5703
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005704 if (!*(args[cur_arg + 1])) {
5705 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5706 file, linenum, args[0], args[1], ptr_arg);
5707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
5709 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005710
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005711 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005712
5713 tcpcheck->action = TCPCHK_ACT_EXPECT;
5714 tcpcheck->string_len = 0;
5715 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005716 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5717 error = NULL;
5718 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5719 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5720 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5721 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
5725 tcpcheck->inverse = inverse;
5726
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005727 /* tcpcheck comment */
5728 cur_arg += 2;
5729 if (strcmp(args[cur_arg], "comment") == 0) {
5730 if (!*args[cur_arg + 1]) {
5731 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5732 file, linenum, args[cur_arg + 1]);
5733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
5736 tcpcheck->comment = strdup(args[cur_arg + 1]);
5737 }
5738
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005739 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5740 }
5741 else {
5742 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5743 file, linenum, args[0], args[1], ptr_arg);
5744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
5747 }
5748 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005749 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
5752 }
5753 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005754 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005755 if (curproxy == &defproxy) {
5756 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005757 err_code |= ERR_ALERT | ERR_FATAL;
5758 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005759 }
5760
Willy Tarreaub80c2302007-11-30 20:51:32 +01005761 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005763
5764 if (strcmp(args[1], "fail") == 0) {
5765 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005766 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005767 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5768 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005771 }
5772
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005773 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5774 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5775 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005778 }
5779 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5780 }
5781 else {
5782 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005783 err_code |= ERR_ALERT | ERR_FATAL;
5784 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005785 }
5786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787#ifdef TPROXY
5788 else if (!strcmp(args[0], "transparent")) {
5789 /* enable transparent proxy connections */
5790 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005791 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 }
5794#endif
5795 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005796 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005798
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 if (*(args[1]) == 0) {
5800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 }
5804 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005808 else if (!strcmp(args[0], "backlog")) { /* backlog */
5809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005811
5812 if (*(args[1]) == 0) {
5813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005816 }
5817 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005818 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5819 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005820 }
Willy Tarreau86034312006-12-29 00:10:33 +01005821 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005824
Willy Tarreau86034312006-12-29 00:10:33 +01005825 if (*(args[1]) == 0) {
5826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005829 }
5830 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005831 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5832 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5835 if (*(args[1]) == 0) {
5836 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005840 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5841 if (err) {
5842 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5843 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005846 }
5847 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005848 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 }
5851 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005852 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005853 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005854 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005855
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 if (curproxy == &defproxy) {
5857 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005861 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005862 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005863
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005864 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005865 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005866 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005867 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005868 goto out;
5869 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005870
5871 proto = protocol_by_family(sk->ss_family);
5872 if (!proto || !proto->connect) {
5873 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5874 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
5878
5879 if (port1 != port2) {
5880 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5881 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005885
5886 if (!port1) {
5887 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5888 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
5891 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005892
William Lallemanddf1425a2015-04-28 20:17:49 +02005893 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5894 goto out;
5895
Willy Tarreaud5191e72010-02-09 20:50:45 +01005896 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005897 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 }
5899 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005902
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005903 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5904 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005909 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005910 /**
5911 * The syntax for hash-type config element is
5912 * hash-type {map-based|consistent} [[<algo>] avalanche]
5913 *
5914 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5915 */
5916 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005917
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5919 err_code |= ERR_WARN;
5920
5921 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005922 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5923 }
5924 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005925 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5926 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005927 else if (strcmp(args[1], "avalanche") == 0) {
5928 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]);
5929 err_code |= ERR_ALERT | ERR_FATAL;
5930 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005931 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005932 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005933 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
5936 }
Bhaskar98634f02013-10-29 23:30:51 -04005937
5938 /* set the hash function to use */
5939 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005940 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005941 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005942
5943 /* if consistent with no argument, then avalanche modifier is also applied */
5944 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5945 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005946 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005947 /* set the hash function */
5948 if (!strcmp(args[2], "sdbm")) {
5949 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5950 }
5951 else if (!strcmp(args[2], "djb2")) {
5952 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005953 }
5954 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005955 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005956 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005957 else if (!strcmp(args[2], "crc32")) {
5958 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5959 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005960 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005961 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 -05005962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
5965
5966 /* set the hash modifier */
5967 if (!strcmp(args[3], "avalanche")) {
5968 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5969 }
5970 else if (*args[3]) {
5971 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005975 }
William Lallemanda73203e2012-03-12 12:48:57 +01005976 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005977 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5978 if (*(args[1]) == 0) {
5979 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
5982 }
5983 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5984 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5985 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
5988 }
5989 }
William Lallemanda73203e2012-03-12 12:48:57 +01005990 else if (strcmp(args[0], "unique-id-format") == 0) {
5991 if (!*(args[1])) {
5992 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
William Lallemand3203ff42012-11-11 17:30:56 +01005996 if (*(args[2])) {
5997 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006001 free(curproxy->conf.uniqueid_format_string);
6002 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006003
Willy Tarreau62a61232013-04-12 18:13:46 +02006004 free(curproxy->conf.uif_file);
6005 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6006 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006007 }
William Lallemanda73203e2012-03-12 12:48:57 +01006008
6009 else if (strcmp(args[0], "unique-id-header") == 0) {
6010 if (!*(args[1])) {
6011 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6012 err_code |= ERR_ALERT | ERR_FATAL;
6013 goto out;
6014 }
6015 free(curproxy->header_unique_id);
6016 curproxy->header_unique_id = strdup(args[1]);
6017 }
6018
William Lallemand723b73a2012-02-08 16:37:49 +01006019 else if (strcmp(args[0], "log-format") == 0) {
6020 if (!*(args[1])) {
6021 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6022 err_code |= ERR_ALERT | ERR_FATAL;
6023 goto out;
6024 }
William Lallemand3203ff42012-11-11 17:30:56 +01006025 if (*(args[2])) {
6026 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006030
Willy Tarreau62a61232013-04-12 18:13:46 +02006031 if (curproxy->conf.logformat_string != default_http_log_format &&
6032 curproxy->conf.logformat_string != default_tcp_log_format &&
6033 curproxy->conf.logformat_string != clf_http_log_format)
6034 free(curproxy->conf.logformat_string);
6035 curproxy->conf.logformat_string = strdup(args[1]);
6036
6037 free(curproxy->conf.lfs_file);
6038 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6039 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006040
6041 /* get a chance to improve log-format error reporting by
6042 * reporting the correct line-number when possible.
6043 */
6044 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6045 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6046 file, linenum, curproxy->id);
6047 err_code |= ERR_WARN;
6048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006050 else if (!strcmp(args[0], "log-format-sd")) {
6051 if (!*(args[1])) {
6052 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
6056 if (*(args[2])) {
6057 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6058 err_code |= ERR_ALERT | ERR_FATAL;
6059 goto out;
6060 }
6061
6062 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6063 free(curproxy->conf.logformat_sd_string);
6064 curproxy->conf.logformat_sd_string = strdup(args[1]);
6065
6066 free(curproxy->conf.lfsd_file);
6067 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6068 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6069
6070 /* get a chance to improve log-format-sd error reporting by
6071 * reporting the correct line-number when possible.
6072 */
6073 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6074 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6075 file, linenum, curproxy->id);
6076 err_code |= ERR_WARN;
6077 }
6078 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006079 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6080 if (*(args[1]) == 0) {
6081 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
6084 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006085 chunk_destroy(&curproxy->log_tag);
6086 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006087 }
William Lallemand0f99e342011-10-12 17:50:54 +02006088 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6089 /* delete previous herited or defined syslog servers */
6090 struct logsrv *back;
6091
6092 if (*(args[1]) != 0) {
6093 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
6096 }
6097
William Lallemand723b73a2012-02-08 16:37:49 +01006098 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6099 LIST_DEL(&tmplogsrv->list);
6100 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006101 }
6102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006104 struct logsrv *logsrv;
6105
Willy Tarreaubaaee002006-06-26 02:48:02 +02006106 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006107 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006108 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006109 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006110 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006111 LIST_INIT(&node->list);
6112 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 }
6115 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006116 struct sockaddr_storage *sk;
6117 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006118 int arg = 0;
6119 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006120
Vincent Bernat02779b62016-04-03 13:48:43 +02006121 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006122
Willy Tarreau18324f52014-06-27 18:10:07 +02006123 /* just after the address, a length may be specified */
6124 if (strcmp(args[arg+2], "len") == 0) {
6125 len = atoi(args[arg+3]);
6126 if (len < 80 || len > 65535) {
6127 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6128 file, linenum, args[arg+3]);
6129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
6131 }
6132 logsrv->maxlen = len;
6133
6134 /* skip these two args */
6135 arg += 2;
6136 }
6137 else
6138 logsrv->maxlen = MAX_SYSLOG_LEN;
6139
6140 if (logsrv->maxlen > global.max_syslog_len) {
6141 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006142 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6143 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6144 logline = my_realloc2(logline, global.max_syslog_len + 1);
6145 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006146 }
6147
Dragan Dosen1322d092015-09-22 16:05:32 +02006148 /* after the length, a format may be specified */
6149 if (strcmp(args[arg+2], "format") == 0) {
6150 logsrv->format = get_log_format(args[arg+3]);
6151 if (logsrv->format < 0) {
6152 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155 }
6156
6157 /* skip these two args */
6158 arg += 2;
6159 }
6160
William Lallemanddf1425a2015-04-28 20:17:49 +02006161 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6162 goto out;
6163
Willy Tarreau18324f52014-06-27 18:10:07 +02006164 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006165 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006166 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006167 err_code |= ERR_ALERT | ERR_FATAL;
6168 goto out;
6169
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 }
6171
William Lallemand0f99e342011-10-12 17:50:54 +02006172 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006173 if (*(args[arg+3])) {
6174 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006175 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006176 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006177 err_code |= ERR_ALERT | ERR_FATAL;
6178 goto out;
6179
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180 }
6181 }
6182
William Lallemand0f99e342011-10-12 17:50:54 +02006183 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006184 if (*(args[arg+4])) {
6185 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006186 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006187 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006188 err_code |= ERR_ALERT | ERR_FATAL;
6189 goto out;
6190
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006191 }
6192 }
6193
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006194 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006195 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006196 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006197 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006198 goto out;
6199 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006200
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006201 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006202
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006203 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006204 if (port1 != port2) {
6205 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6206 file, linenum, args[0], args[1]);
6207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
6209 }
6210
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006211 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006212 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 }
William Lallemand0f99e342011-10-12 17:50:54 +02006214
6215 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
6217 else {
6218 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6219 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006220 err_code |= ERR_ALERT | ERR_FATAL;
6221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006222 }
6223 }
6224 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006225 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006226 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006227 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006228 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006229
Willy Tarreau977b8e42006-12-29 14:19:17 +01006230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006231 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006232
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006234 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6235 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006236 err_code |= ERR_ALERT | ERR_FATAL;
6237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006238 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006239
6240 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006241 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6242 free(curproxy->conn_src.iface_name);
6243 curproxy->conn_src.iface_name = NULL;
6244 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006245
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006246 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006247 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006248 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006249 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006250 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006251 goto out;
6252 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006253
6254 proto = protocol_by_family(sk->ss_family);
6255 if (!proto || !proto->connect) {
6256 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006257 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006258 err_code |= ERR_ALERT | ERR_FATAL;
6259 goto out;
6260 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006261
6262 if (port1 != port2) {
6263 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6264 file, linenum, args[0], args[1]);
6265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
6267 }
6268
Willy Tarreauef9a3602012-12-08 22:29:20 +01006269 curproxy->conn_src.source_addr = *sk;
6270 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006271
6272 cur_arg = 2;
6273 while (*(args[cur_arg])) {
6274 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006275#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006276 if (!*args[cur_arg + 1]) {
6277 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6278 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006281 }
6282
6283 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006284 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6285 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006286 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006287 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6288 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006289 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6290 char *name, *end;
6291
6292 name = args[cur_arg+1] + 7;
6293 while (isspace(*name))
6294 name++;
6295
6296 end = name;
6297 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6298 end++;
6299
Willy Tarreauef9a3602012-12-08 22:29:20 +01006300 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6301 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6302 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6303 curproxy->conn_src.bind_hdr_len = end - name;
6304 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6305 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6306 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006307
6308 /* now look for an occurrence number */
6309 while (isspace(*end))
6310 end++;
6311 if (*end == ',') {
6312 end++;
6313 name = end;
6314 if (*end == '-')
6315 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006316 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006317 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006318 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006319 }
6320
Willy Tarreauef9a3602012-12-08 22:29:20 +01006321 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006322 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6323 " occurrences values smaller than %d.\n",
6324 file, linenum, MAX_HDR_HISTORY);
6325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
6327 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006328 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006329 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006330
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006331 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006332 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006333 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006334 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006335 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006336 goto out;
6337 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006338
6339 proto = protocol_by_family(sk->ss_family);
6340 if (!proto || !proto->connect) {
6341 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6342 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006343 err_code |= ERR_ALERT | ERR_FATAL;
6344 goto out;
6345 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006346
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006347 if (port1 != port2) {
6348 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6349 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006350 err_code |= ERR_ALERT | ERR_FATAL;
6351 goto out;
6352 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006353 curproxy->conn_src.tproxy_addr = *sk;
6354 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006355 }
6356 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006357#else /* no TPROXY support */
6358 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006359 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006360 err_code |= ERR_ALERT | ERR_FATAL;
6361 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006362#endif
6363 cur_arg += 2;
6364 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006365 }
6366
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006367 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6368#ifdef SO_BINDTODEVICE
6369 if (!*args[cur_arg + 1]) {
6370 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6371 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006372 err_code |= ERR_ALERT | ERR_FATAL;
6373 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006374 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006375 free(curproxy->conn_src.iface_name);
6376 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6377 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006378 global.last_checks |= LSTCHK_NETADM;
6379#else
6380 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6381 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006382 err_code |= ERR_ALERT | ERR_FATAL;
6383 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006384#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006385 cur_arg += 2;
6386 continue;
6387 }
6388 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006389 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006390 err_code |= ERR_ALERT | ERR_FATAL;
6391 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006394 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6395 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6396 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006397 err_code |= ERR_ALERT | ERR_FATAL;
6398 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407
6408 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006409 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006410 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006416 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006417 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006424 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
6435 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006442 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006444 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006445 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006447 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6452 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456
6457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006459 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
6477 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006479 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006486 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006487 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006488 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006491 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006493 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006494 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006496 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006499 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006500
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 if (curproxy == &defproxy) {
6502 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006503 err_code |= ERR_ALERT | ERR_FATAL;
6504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006506 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006507 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 if (*(args[1]) == 0) {
6510 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006511 err_code |= ERR_ALERT | ERR_FATAL;
6512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006514
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006515 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006516 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6517 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6518 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006519 err_code |= ERR_ALERT | ERR_FATAL;
6520 goto out;
6521 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006522 err_code |= warnif_cond_conflicts(cond,
6523 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6524 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006525 }
6526 else if (*args[2]) {
6527 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6528 file, linenum, args[0], args[2]);
6529 err_code |= ERR_ALERT | ERR_FATAL;
6530 goto out;
6531 }
6532
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006533 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006534 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006535 wl->s = strdup(args[1]);
6536 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006537 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 }
6539 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006540 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_ALERT | ERR_FATAL;
6544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006546
Willy Tarreauade5ec42010-01-28 19:33:49 +01006547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006548 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006549 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
6553 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006554 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006555 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006556 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006557 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559 }
6560 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006561 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006562 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006563 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566 }
6567 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006568 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006571 err_code |= ERR_ALERT | ERR_FATAL;
6572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 }
6574
Willy Tarreauade5ec42010-01-28 19:33:49 +01006575 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006576 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006577 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006578 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 }
6581 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006582 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006583 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006584 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006585 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 }
6588 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006589 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006590 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006591 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006592 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 }
6595 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006596 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006597
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 if (curproxy == &defproxy) {
6599 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006600 err_code |= ERR_ALERT | ERR_FATAL;
6601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006603 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006604 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 if (*(args[1]) == 0) {
6607 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006608 err_code |= ERR_ALERT | ERR_FATAL;
6609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 }
6611
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006612 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006613 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6614 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6615 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006616 err_code |= ERR_ALERT | ERR_FATAL;
6617 goto out;
6618 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006619 err_code |= warnif_cond_conflicts(cond,
6620 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6621 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006622 }
6623 else if (*args[2]) {
6624 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6625 file, linenum, args[0], args[2]);
6626 err_code |= ERR_ALERT | ERR_FATAL;
6627 goto out;
6628 }
6629
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006630 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006631 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006632 wl->s = strdup(args[1]);
6633 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634 }
6635 else if (!strcmp(args[0], "errorloc") ||
6636 !strcmp(args[0], "errorloc302") ||
6637 !strcmp(args[0], "errorloc303")) { /* error location */
6638 int errnum, errlen;
6639 char *err;
6640
Willy Tarreau977b8e42006-12-29 14:19:17 +01006641 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006642 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006643
Willy Tarreaubaaee002006-06-26 02:48:02 +02006644 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006645 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006646 err_code |= ERR_ALERT | ERR_FATAL;
6647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006648 }
6649
6650 errnum = atol(args[1]);
6651 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006652 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6653 err = malloc(errlen);
6654 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006655 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006656 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6657 err = malloc(errlen);
6658 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006659 }
6660
Willy Tarreau0f772532006-12-23 20:51:41 +01006661 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6662 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006663 chunk_destroy(&curproxy->errmsg[rc]);
6664 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006665 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006668
6669 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006670 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6671 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006672 free(err);
6673 }
6674 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006675 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6676 int errnum, errlen, fd;
6677 char *err;
6678 struct stat stat;
6679
6680 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006681 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006682
6683 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006684 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006685 err_code |= ERR_ALERT | ERR_FATAL;
6686 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006687 }
6688
6689 fd = open(args[2], O_RDONLY);
6690 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6691 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6692 file, linenum, args[2], args[1]);
6693 if (fd >= 0)
6694 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006695 err_code |= ERR_ALERT | ERR_FATAL;
6696 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006697 }
6698
Willy Tarreau27a674e2009-08-17 07:23:33 +02006699 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006700 errlen = stat.st_size;
6701 } else {
6702 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006703 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006704 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006705 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006706 }
6707
6708 err = malloc(errlen); /* malloc() must succeed during parsing */
6709 errnum = read(fd, err, errlen);
6710 if (errnum != errlen) {
6711 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6712 file, linenum, args[2], args[1]);
6713 close(fd);
6714 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006715 err_code |= ERR_ALERT | ERR_FATAL;
6716 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006717 }
6718 close(fd);
6719
6720 errnum = atol(args[1]);
6721 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6722 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006723 chunk_destroy(&curproxy->errmsg[rc]);
6724 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006725 break;
6726 }
6727 }
6728
6729 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006730 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6731 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006732 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006733 free(err);
6734 }
6735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006736 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006737 struct cfg_kw_list *kwl;
6738 int index;
6739
6740 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6741 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6742 if (kwl->kw[index].section != CFG_LISTEN)
6743 continue;
6744 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6745 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006746 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006747 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006748 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006749 err_code |= ERR_ALERT | ERR_FATAL;
6750 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006751 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006752 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006753 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006754 err_code |= ERR_WARN;
6755 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006756 }
Willy Tarreau93893792009-07-23 13:19:11 +02006757 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006758 }
6759 }
6760 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006761
Willy Tarreau6daf3432008-01-22 16:44:08 +01006762 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006763 err_code |= ERR_ALERT | ERR_FATAL;
6764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006765 }
Willy Tarreau93893792009-07-23 13:19:11 +02006766 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006767 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006768 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006769}
6770
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006772cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6773{
6774#ifdef CONFIG_HAP_NS
6775 const char *err;
6776 const char *item = args[0];
6777
6778 if (!strcmp(item, "namespace_list")) {
6779 return 0;
6780 }
6781 else if (!strcmp(item, "namespace")) {
6782 size_t idx = 1;
6783 const char *current;
6784 while (*(current = args[idx++])) {
6785 err = invalid_char(current);
6786 if (err) {
6787 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6788 file, linenum, *err, item, current);
6789 return ERR_ALERT | ERR_FATAL;
6790 }
6791
6792 if (netns_store_lookup(current, strlen(current))) {
6793 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6794 file, linenum, current);
6795 return ERR_ALERT | ERR_FATAL;
6796 }
6797 if (!netns_store_insert(current)) {
6798 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6799 file, linenum, current);
6800 return ERR_ALERT | ERR_FATAL;
6801 }
6802 }
6803 }
6804
6805 return 0;
6806#else
6807 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6808 file, linenum);
6809 return ERR_ALERT | ERR_FATAL;
6810#endif
6811}
6812
6813int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6815{
6816
6817 int err_code = 0;
6818 const char *err;
6819
6820 if (!strcmp(args[0], "userlist")) { /* new userlist */
6821 struct userlist *newul;
6822
6823 if (!*args[1]) {
6824 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6825 file, linenum, args[0]);
6826 err_code |= ERR_ALERT | ERR_FATAL;
6827 goto out;
6828 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006829 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6830 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006831
6832 err = invalid_char(args[1]);
6833 if (err) {
6834 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6835 file, linenum, *err, args[0], args[1]);
6836 err_code |= ERR_ALERT | ERR_FATAL;
6837 goto out;
6838 }
6839
6840 for (newul = userlist; newul; newul = newul->next)
6841 if (!strcmp(newul->name, args[1])) {
6842 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6843 file, linenum, args[1]);
6844 err_code |= ERR_WARN;
6845 goto out;
6846 }
6847
Vincent Bernat02779b62016-04-03 13:48:43 +02006848 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006849 if (!newul) {
6850 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6851 err_code |= ERR_ALERT | ERR_ABORT;
6852 goto out;
6853 }
6854
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006856 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6858 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006859 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860 goto out;
6861 }
6862
6863 newul->next = userlist;
6864 userlist = newul;
6865
6866 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006867 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006869 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870
6871 if (!*args[1]) {
6872 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6873 file, linenum, args[0]);
6874 err_code |= ERR_ALERT | ERR_FATAL;
6875 goto out;
6876 }
6877
6878 err = invalid_char(args[1]);
6879 if (err) {
6880 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6881 file, linenum, *err, args[0], args[1]);
6882 err_code |= ERR_ALERT | ERR_FATAL;
6883 goto out;
6884 }
6885
William Lallemand4ac9f542015-05-28 18:03:51 +02006886 if (!userlist)
6887 goto out;
6888
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006889 for (ag = userlist->groups; ag; ag = ag->next)
6890 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006891 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6892 file, linenum, args[1], userlist->name);
6893 err_code |= ERR_ALERT;
6894 goto out;
6895 }
6896
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006897 ag = calloc(1, sizeof(*ag));
6898 if (!ag) {
6899 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6900 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006901 goto out;
6902 }
6903
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006904 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006905 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006906 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6907 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006908 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006909 goto out;
6910 }
6911
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006912 cur_arg = 2;
6913
6914 while (*args[cur_arg]) {
6915 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006916 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006917 cur_arg += 2;
6918 continue;
6919 } else {
6920 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6921 file, linenum, args[0]);
6922 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006923 free(ag->groupusers);
6924 free(ag->name);
6925 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006926 goto out;
6927 }
6928 }
6929
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006930 ag->next = userlist->groups;
6931 userlist->groups = ag;
6932
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006933 } else if (!strcmp(args[0], "user")) { /* new user */
6934 struct auth_users *newuser;
6935 int cur_arg;
6936
6937 if (!*args[1]) {
6938 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6939 file, linenum, args[0]);
6940 err_code |= ERR_ALERT | ERR_FATAL;
6941 goto out;
6942 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006943 if (!userlist)
6944 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006945
6946 for (newuser = userlist->users; newuser; newuser = newuser->next)
6947 if (!strcmp(newuser->user, args[1])) {
6948 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6949 file, linenum, args[1], userlist->name);
6950 err_code |= ERR_ALERT;
6951 goto out;
6952 }
6953
Vincent Bernat02779b62016-04-03 13:48:43 +02006954 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006955 if (!newuser) {
6956 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6957 err_code |= ERR_ALERT | ERR_ABORT;
6958 goto out;
6959 }
6960
6961 newuser->user = strdup(args[1]);
6962
6963 newuser->next = userlist->users;
6964 userlist->users = newuser;
6965
6966 cur_arg = 2;
6967
6968 while (*args[cur_arg]) {
6969 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006970#ifdef CONFIG_HAP_CRYPT
6971 if (!crypt("", args[cur_arg + 1])) {
6972 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6973 file, linenum, newuser->user);
6974 err_code |= ERR_ALERT | ERR_FATAL;
6975 goto out;
6976 }
6977#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006978 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6979 file, linenum);
6980 err_code |= ERR_ALERT;
6981#endif
6982 newuser->pass = strdup(args[cur_arg + 1]);
6983 cur_arg += 2;
6984 continue;
6985 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6986 newuser->pass = strdup(args[cur_arg + 1]);
6987 newuser->flags |= AU_O_INSECURE;
6988 cur_arg += 2;
6989 continue;
6990 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006991 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006992 cur_arg += 2;
6993 continue;
6994 } else {
6995 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6996 file, linenum, args[0]);
6997 err_code |= ERR_ALERT | ERR_FATAL;
6998 goto out;
6999 }
7000 }
7001 } else {
7002 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7003 err_code |= ERR_ALERT | ERR_FATAL;
7004 }
7005
7006out:
7007 return err_code;
7008}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007009
Christopher Faulet79bdef32016-11-04 22:36:15 +01007010int
7011cfg_parse_scope(const char *file, int linenum, char *line)
7012{
7013 char *beg, *end, *scope = NULL;
7014 int err_code = 0;
7015 const char *err;
7016
7017 beg = line + 1;
7018 end = strchr(beg, ']');
7019
7020 /* Detect end of scope declaration */
7021 if (!end || end == beg) {
7022 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7023 file, linenum);
7024 err_code |= ERR_ALERT | ERR_FATAL;
7025 goto out;
7026 }
7027
7028 /* Get scope name and check its validity */
7029 scope = my_strndup(beg, end-beg);
7030 err = invalid_char(scope);
7031 if (err) {
7032 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7033 file, linenum, *err);
7034 err_code |= ERR_ALERT | ERR_ABORT;
7035 goto out;
7036 }
7037
7038 /* Be sure to have a scope declaration alone on its line */
7039 line = end+1;
7040 while (isspace((unsigned char)*line))
7041 line++;
7042 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7043 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7044 file, linenum, *line);
7045 err_code |= ERR_ALERT | ERR_ABORT;
7046 goto out;
7047 }
7048
7049 /* We have a valid scope declaration, save it */
7050 free(cfg_scope);
7051 cfg_scope = scope;
7052 scope = NULL;
7053
7054 out:
7055 free(scope);
7056 return err_code;
7057}
7058
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059/*
7060 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007061 * Returns the error code, 0 if OK, or any combination of :
7062 * - ERR_ABORT: must abort ASAP
7063 * - ERR_FATAL: we can continue parsing but not start the service
7064 * - ERR_WARN: a warning has been emitted
7065 * - ERR_ALERT: an alert has been emitted
7066 * Only the two first ones can stop processing, the two others are just
7067 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007068 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007069int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007070{
William Lallemand64e84512015-05-12 14:25:37 +02007071 char *thisline;
7072 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007073 FILE *f;
7074 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007075 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007076 struct cfg_section *cs = NULL;
7077 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007078 int readbytes = 0;
7079
7080 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007081 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007082 return -1;
7083 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007084
David Carlier97880bb2016-04-08 10:35:26 +01007085 if ((f=fopen(file,"r")) == NULL) {
7086 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007089
William Lallemandb2f07452015-05-12 14:27:13 +02007090next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007091 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007092 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007093 char *end;
7094 char *args[MAX_LINE_ARGS + 1];
7095 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007096 int dquote = 0; /* double quote */
7097 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007098
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099 linenum++;
7100
7101 end = line + strlen(line);
7102
William Lallemand64e84512015-05-12 14:25:37 +02007103 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007104 /* Check if we reached the limit and the last char is not \n.
7105 * Watch out for the last line without the terminating '\n'!
7106 */
William Lallemand64e84512015-05-12 14:25:37 +02007107 char *newline;
7108 int newlinesize = linesize * 2;
7109
7110 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7111 if (newline == NULL) {
7112 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7113 file, linenum);
7114 err_code |= ERR_ALERT | ERR_FATAL;
7115 continue;
7116 }
7117
7118 readbytes = linesize - 1;
7119 linesize = newlinesize;
7120 thisline = newline;
7121 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007122 }
7123
William Lallemand64e84512015-05-12 14:25:37 +02007124 readbytes = 0;
7125
Willy Tarreaubaaee002006-06-26 02:48:02 +02007126 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007127 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007129
Christopher Faulet79bdef32016-11-04 22:36:15 +01007130
7131 if (*line == '[') {/* This is the begining if a scope */
7132 err_code |= cfg_parse_scope(file, linenum, line);
7133 goto next_line;
7134 }
7135
Willy Tarreaubaaee002006-06-26 02:48:02 +02007136 arg = 0;
7137 args[arg] = line;
7138
7139 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007140 if (*line == '"' && !squote) { /* double quote outside single quotes */
7141 if (dquote)
7142 dquote = 0;
7143 else
7144 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007145 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007146 end--;
7147 }
7148 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7149 if (squote)
7150 squote = 0;
7151 else
7152 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007153 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007154 end--;
7155 }
7156 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7158 * C equivalent value. Other combinations left unchanged (eg: \1).
7159 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160 int skip = 0;
7161 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7162 *line = line[1];
7163 skip = 1;
7164 }
7165 else if (line[1] == 'r') {
7166 *line = '\r';
7167 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007169 else if (line[1] == 'n') {
7170 *line = '\n';
7171 skip = 1;
7172 }
7173 else if (line[1] == 't') {
7174 *line = '\t';
7175 skip = 1;
7176 }
7177 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007178 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179 unsigned char hex1, hex2;
7180 hex1 = toupper(line[2]) - '0';
7181 hex2 = toupper(line[3]) - '0';
7182 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7183 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7184 *line = (hex1<<4) + hex2;
7185 skip = 3;
7186 }
7187 else {
7188 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007189 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007190 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007191 } else if (line[1] == '"') {
7192 *line = '"';
7193 skip = 1;
7194 } else if (line[1] == '\'') {
7195 *line = '\'';
7196 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007197 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7198 *line = '$';
7199 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007200 }
7201 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007202 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007203 end -= skip;
7204 }
7205 line++;
7206 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007207 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007208 /* end of string, end of loop */
7209 *line = 0;
7210 break;
7211 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007212 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007213 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007214 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007215 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216 line++;
7217 args[++arg] = line;
7218 }
William Lallemandb2f07452015-05-12 14:27:13 +02007219 else if (dquote && *line == '$') {
7220 /* environment variables are evaluated inside double quotes */
7221 char *var_beg;
7222 char *var_end;
7223 char save_char;
7224 char *value;
7225 int val_len;
7226 int newlinesize;
7227 int braces = 0;
7228
7229 var_beg = line + 1;
7230 var_end = var_beg;
7231
7232 if (*var_beg == '{') {
7233 var_beg++;
7234 var_end++;
7235 braces = 1;
7236 }
7237
7238 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7239 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7240 err_code |= ERR_ALERT | ERR_FATAL;
7241 goto next_line; /* skip current line */
7242 }
7243
7244 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7245 var_end++;
7246
7247 save_char = *var_end;
7248 *var_end = '\0';
7249 value = getenv(var_beg);
7250 *var_end = save_char;
7251 val_len = value ? strlen(value) : 0;
7252
7253 if (braces) {
7254 if (*var_end == '}') {
7255 var_end++;
7256 braces = 0;
7257 } else {
7258 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7259 err_code |= ERR_ALERT | ERR_FATAL;
7260 goto next_line; /* skip current line */
7261 }
7262 }
7263
7264 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7265
7266 /* if not enough space in thisline */
7267 if (newlinesize > linesize) {
7268 char *newline;
7269
7270 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7271 if (newline == NULL) {
7272 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7273 err_code |= ERR_ALERT | ERR_FATAL;
7274 goto next_line; /* slip current line */
7275 }
7276 /* recompute pointers if realloc returns a new pointer */
7277 if (newline != thisline) {
7278 int i;
7279 int diff;
7280
7281 for (i = 0; i <= arg; i++) {
7282 diff = args[i] - thisline;
7283 args[i] = newline + diff;
7284 }
7285
7286 diff = var_end - thisline;
7287 var_end = newline + diff;
7288 diff = end - thisline;
7289 end = newline + diff;
7290 diff = line - thisline;
7291 line = newline + diff;
7292 thisline = newline;
7293 }
7294 linesize = newlinesize;
7295 }
7296
7297 /* insert value inside the line */
7298 memmove(line + val_len, var_end, end - var_end + 1);
7299 memcpy(line, value, val_len);
7300 end += val_len - (var_end - line);
7301 line += val_len;
7302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007303 else {
7304 line++;
7305 }
7306 }
William Lallemandb2f07452015-05-12 14:27:13 +02007307
William Lallemandf9873ba2015-05-05 17:37:14 +02007308 if (dquote) {
7309 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7310 err_code |= ERR_ALERT | ERR_FATAL;
7311 }
7312
7313 if (squote) {
7314 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7315 err_code |= ERR_ALERT | ERR_FATAL;
7316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007317
7318 /* empty line */
7319 if (!**args)
7320 continue;
7321
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007322 if (*line) {
7323 /* we had to stop due to too many args.
7324 * Let's terminate the string, print the offending part then cut the
7325 * last arg.
7326 */
7327 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7328 line++;
7329 *line = '\0';
7330
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007331 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007332 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007333 err_code |= ERR_ALERT | ERR_FATAL;
7334 args[arg] = line;
7335 }
7336
Willy Tarreau540abe42007-05-02 20:50:16 +02007337 /* zero out remaining args and ensure that at least one entry
7338 * is zeroed out.
7339 */
7340 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007341 args[arg] = line;
7342 }
7343
Willy Tarreau3842f002009-06-14 11:39:52 +02007344 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007345 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007346 char *tmp;
7347
Willy Tarreau3842f002009-06-14 11:39:52 +02007348 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007349 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007350 for (arg=0; *args[arg+1]; arg++)
7351 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007352 *tmp = '\0'; // fix the next arg to \0
7353 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007354 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007355 else if (!strcmp(args[0], "default")) {
7356 kwm = KWM_DEF;
7357 for (arg=0; *args[arg+1]; arg++)
7358 args[arg] = args[arg+1]; // shift args after inversion
7359 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007360
William Lallemand0f99e342011-10-12 17:50:54 +02007361 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7362 strcmp(args[0], "log") != 0) {
7363 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007364 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007365 }
7366
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007367 /* detect section start */
7368 list_for_each_entry(ics, &sections, list) {
7369 if (strcmp(args[0], ics->section_name) == 0) {
7370 cursection = ics->section_name;
7371 cs = ics;
7372 break;
7373 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007374 }
7375
Willy Tarreaubaaee002006-06-26 02:48:02 +02007376 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007377 if (cs)
7378 err_code |= cs->section_parser(file, linenum, args, kwm);
7379 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007380 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007382 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007383
7384 if (err_code & ERR_ABORT)
7385 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007386 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007387 free(cfg_scope);
7388 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007389 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007390 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007391 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007392 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007393}
7394
Willy Tarreau64ab6072014-09-16 12:17:36 +02007395/* This function propagates processes from frontend <from> to backend <to> so
7396 * that it is always guaranteed that a backend pointed to by a frontend is
7397 * bound to all of its processes. After that, if the target is a "listen"
7398 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007399 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007400 * checked first to ensure that <to> is already bound to all processes of
7401 * <from>, there is no risk of looping and we ensure to follow the shortest
7402 * path to the destination.
7403 *
7404 * It is possible to set <to> to NULL for the first call so that the function
7405 * takes care of visiting the initial frontend in <from>.
7406 *
7407 * It is important to note that the function relies on the fact that all names
7408 * have already been resolved.
7409 */
7410void propagate_processes(struct proxy *from, struct proxy *to)
7411{
7412 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007413
7414 if (to) {
7415 /* check whether we need to go down */
7416 if (from->bind_proc &&
7417 (from->bind_proc & to->bind_proc) == from->bind_proc)
7418 return;
7419
7420 if (!from->bind_proc && !to->bind_proc)
7421 return;
7422
7423 to->bind_proc = from->bind_proc ?
7424 (to->bind_proc | from->bind_proc) : 0;
7425
7426 /* now propagate down */
7427 from = to;
7428 }
7429
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007430 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007431 return;
7432
Willy Tarreauf6b70012014-12-18 14:00:43 +01007433 if (from->state == PR_STSTOPPED)
7434 return;
7435
Willy Tarreau64ab6072014-09-16 12:17:36 +02007436 /* default_backend */
7437 if (from->defbe.be)
7438 propagate_processes(from, from->defbe.be);
7439
7440 /* use_backend */
7441 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007442 if (rule->dynamic)
7443 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007444 to = rule->be.backend;
7445 propagate_processes(from, to);
7446 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007447}
7448
Willy Tarreaubb925012009-07-23 13:36:36 +02007449/*
7450 * Returns the error code, 0 if OK, or any combination of :
7451 * - ERR_ABORT: must abort ASAP
7452 * - ERR_FATAL: we can continue parsing but not start the service
7453 * - ERR_WARN: a warning has been emitted
7454 * - ERR_ALERT: an alert has been emitted
7455 * Only the two first ones can stop processing, the two others are just
7456 * indicators.
7457 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007458int check_config_validity()
7459{
7460 int cfgerr = 0;
7461 struct proxy *curproxy = NULL;
7462 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007463 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007464 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007465 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007466
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007467 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007468 /*
7469 * Now, check for the integrity of all that we have collected.
7470 */
7471
7472 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007473 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007474
Willy Tarreau193b8c62012-11-22 00:17:38 +01007475 if (!global.tune.max_http_hdr)
7476 global.tune.max_http_hdr = MAX_HTTP_HDR;
7477
7478 if (!global.tune.cookie_len)
7479 global.tune.cookie_len = CAPTURE_LEN;
7480
7481 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7482
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007483 /* Post initialisation of the users and groups lists. */
7484 err_code = userlist_postinit();
7485 if (err_code != ERR_NONE)
7486 goto out;
7487
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007488 /* first, we will invert the proxy list order */
7489 curproxy = NULL;
7490 while (proxy) {
7491 struct proxy *next;
7492
7493 next = proxy->next;
7494 proxy->next = curproxy;
7495 curproxy = proxy;
7496 if (!next)
7497 break;
7498 proxy = next;
7499 }
7500
Willy Tarreau419ead82014-09-16 13:41:21 +02007501 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007502 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007503 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007504 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007505 struct act_rule *trule;
7506 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007507 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007508 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007509 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007510
Willy Tarreau050536d2012-10-04 08:47:34 +02007511 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007512 /* proxy ID not set, use automatic numbering with first
7513 * spare entry starting with next_pxid.
7514 */
7515 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7516 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7517 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007518 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007519 next_pxid++;
7520
Willy Tarreau55ea7572007-06-17 19:56:27 +02007521
Willy Tarreaubaaee002006-06-26 02:48:02 +02007522 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007523 /* ensure we don't keep listeners uselessly bound */
7524 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007525 free((void *)curproxy->table.peers.name);
7526 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007527 continue;
7528 }
7529
Willy Tarreau102df612014-05-07 23:56:38 +02007530 /* Check multi-process mode compatibility for the current proxy */
7531
7532 if (curproxy->bind_proc) {
7533 /* an explicit bind-process was specified, let's check how many
7534 * processes remain.
7535 */
David Carliere6c39412015-07-02 07:00:17 +00007536 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007537
7538 curproxy->bind_proc &= nbits(global.nbproc);
7539 if (!curproxy->bind_proc && nbproc == 1) {
7540 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);
7541 curproxy->bind_proc = 1;
7542 }
7543 else if (!curproxy->bind_proc && nbproc > 1) {
7544 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);
7545 curproxy->bind_proc = 0;
7546 }
7547 }
7548
Willy Tarreau3d209582014-05-09 17:06:11 +02007549 /* check and reduce the bind-proc of each listener */
7550 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7551 unsigned long mask;
7552
7553 if (!bind_conf->bind_proc)
7554 continue;
7555
7556 mask = nbits(global.nbproc);
7557 if (curproxy->bind_proc)
7558 mask &= curproxy->bind_proc;
7559 /* mask cannot be null here thanks to the previous checks */
7560
David Carliere6c39412015-07-02 07:00:17 +00007561 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007562 bind_conf->bind_proc &= mask;
7563
7564 if (!bind_conf->bind_proc && nbproc == 1) {
7565 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",
7566 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7567 bind_conf->bind_proc = mask & ~(mask - 1);
7568 }
7569 else if (!bind_conf->bind_proc && nbproc > 1) {
7570 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",
7571 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7572 bind_conf->bind_proc = 0;
7573 }
7574 }
7575
Willy Tarreauff01a212009-03-15 13:46:16 +01007576 switch (curproxy->mode) {
7577 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007578 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007579 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007580 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7581 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007582 cfgerr++;
7583 }
7584
7585 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007586 Warning("config : servers will be ignored for %s '%s'.\n",
7587 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007588 break;
7589
7590 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007591 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007592 break;
7593
7594 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007595 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007596 break;
7597 }
7598
Willy Tarreauf3934b82015-08-11 11:36:45 +02007599 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7600 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7601 proxy_type_str(curproxy), curproxy->id);
7602 err_code |= ERR_WARN;
7603 }
7604
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007605 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007606 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007607 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007608 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007610 cfgerr++;
7611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007612#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007613 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007614 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7615 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007616 cfgerr++;
7617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007618#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007619 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007620 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7621 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007622 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007623 }
7624 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007625 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007626 /* If no LB algo is set in a backend, and we're not in
7627 * transparent mode, dispatch mode nor proxy mode, we
7628 * want to use balance roundrobin by default.
7629 */
7630 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7631 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007632 }
7633 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007634
Willy Tarreau1620ec32011-08-06 17:05:02 +02007635 if (curproxy->options & PR_O_DISPATCH)
7636 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7637 else if (curproxy->options & PR_O_HTTP_PROXY)
7638 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7639 else if (curproxy->options & PR_O_TRANSP)
7640 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007641
Willy Tarreau1620ec32011-08-06 17:05:02 +02007642 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7643 if (curproxy->options & PR_O_DISABLE404) {
7644 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7645 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7646 err_code |= ERR_WARN;
7647 curproxy->options &= ~PR_O_DISABLE404;
7648 }
7649 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7650 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7651 "send-state", proxy_type_str(curproxy), curproxy->id);
7652 err_code |= ERR_WARN;
7653 curproxy->options &= ~PR_O2_CHK_SNDST;
7654 }
Willy Tarreauef781042010-01-27 11:53:01 +01007655 }
7656
Simon Horman98637e52014-06-20 12:30:16 +09007657 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7658 if (!global.external_check) {
7659 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7660 curproxy->id, "option external-check");
7661 cfgerr++;
7662 }
7663 if (!curproxy->check_command) {
7664 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7665 curproxy->id, "option external-check");
7666 cfgerr++;
7667 }
7668 }
7669
Simon Horman64e34162015-02-06 11:11:57 +09007670 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007671 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7672 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007673 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7674 "'email-alert myhostname', or 'email-alert to' "
7675 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007676 "to be present).\n",
7677 proxy_type_str(curproxy), curproxy->id);
7678 err_code |= ERR_WARN;
7679 free_email_alert(curproxy);
7680 }
7681 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007682 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007683 }
7684
Simon Horman98637e52014-06-20 12:30:16 +09007685 if (curproxy->check_command) {
7686 int clear = 0;
7687 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7688 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7689 "external-check command", proxy_type_str(curproxy), curproxy->id);
7690 err_code |= ERR_WARN;
7691 clear = 1;
7692 }
7693 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007694 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007695 curproxy->id, "external-check command");
7696 cfgerr++;
7697 }
7698 if (clear) {
7699 free(curproxy->check_command);
7700 curproxy->check_command = NULL;
7701 }
7702 }
7703
7704 if (curproxy->check_path) {
7705 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7706 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7707 "external-check path", proxy_type_str(curproxy), curproxy->id);
7708 err_code |= ERR_WARN;
7709 free(curproxy->check_path);
7710 curproxy->check_path = NULL;
7711 }
7712 }
7713
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007714 /* if a default backend was specified, let's find it */
7715 if (curproxy->defbe.name) {
7716 struct proxy *target;
7717
Willy Tarreauafb39922015-05-26 12:04:09 +02007718 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007719 if (!target) {
7720 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7721 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007722 cfgerr++;
7723 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007724 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7725 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007726 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007727 } else if (target->mode != curproxy->mode &&
7728 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7729
7730 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7731 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7732 curproxy->conf.file, curproxy->conf.line,
7733 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7734 target->conf.file, target->conf.line);
7735 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007736 } else {
7737 free(curproxy->defbe.name);
7738 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007739
7740 /* Emit a warning if this proxy also has some servers */
7741 if (curproxy->srv) {
7742 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7743 curproxy->id);
7744 err_code |= ERR_WARN;
7745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007746 }
7747 }
7748
Willy Tarreau55ea7572007-06-17 19:56:27 +02007749 /* find the target proxy for 'use_backend' rules */
7750 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007751 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007752 struct logformat_node *node;
7753 char *pxname;
7754
7755 /* Try to parse the string as a log format expression. If the result
7756 * of the parsing is only one entry containing a simple string, then
7757 * it's a standard string corresponding to a static rule, thus the
7758 * parsing is cancelled and be.name is restored to be resolved.
7759 */
7760 pxname = rule->be.name;
7761 LIST_INIT(&rule->be.expr);
7762 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7763 curproxy->conf.args.file, curproxy->conf.args.line);
7764 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7765
7766 if (!LIST_ISEMPTY(&rule->be.expr)) {
7767 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7768 rule->dynamic = 1;
7769 free(pxname);
7770 continue;
7771 }
7772 /* simple string: free the expression and fall back to static rule */
7773 free(node->arg);
7774 free(node);
7775 }
7776
7777 rule->dynamic = 0;
7778 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007779
Willy Tarreauafb39922015-05-26 12:04:09 +02007780 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007781 if (!target) {
7782 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7783 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007784 cfgerr++;
7785 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007786 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7787 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007788 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007789 } else if (target->mode != curproxy->mode &&
7790 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7791
7792 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7793 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7794 curproxy->conf.file, curproxy->conf.line,
7795 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7796 target->conf.file, target->conf.line);
7797 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007798 } else {
7799 free((void *)rule->be.name);
7800 rule->be.backend = target;
7801 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007802 }
7803
Willy Tarreau64ab6072014-09-16 12:17:36 +02007804 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007805 list_for_each_entry(srule, &curproxy->server_rules, list) {
7806 struct server *target = findserver(curproxy, srule->srv.name);
7807
7808 if (!target) {
7809 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7810 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7811 cfgerr++;
7812 continue;
7813 }
7814 free((void *)srule->srv.name);
7815 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007816 }
7817
Emeric Brunb982a3d2010-01-04 15:45:53 +01007818 /* find the target table for 'stick' rules */
7819 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7820 struct proxy *target;
7821
Emeric Brun1d33b292010-01-04 15:47:17 +01007822 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7823 if (mrule->flags & STK_IS_STORE)
7824 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7825
Emeric Brunb982a3d2010-01-04 15:45:53 +01007826 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007827 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007828 else
7829 target = curproxy;
7830
7831 if (!target) {
7832 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7833 curproxy->id, mrule->table.name);
7834 cfgerr++;
7835 }
7836 else if (target->table.size == 0) {
7837 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7838 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7839 cfgerr++;
7840 }
Willy Tarreau12785782012-04-27 21:37:17 +02007841 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7842 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007843 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7844 cfgerr++;
7845 }
7846 else {
7847 free((void *)mrule->table.name);
7848 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007849 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007850 }
7851 }
7852
7853 /* find the target table for 'store response' rules */
7854 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7855 struct proxy *target;
7856
Emeric Brun1d33b292010-01-04 15:47:17 +01007857 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7858
Emeric Brunb982a3d2010-01-04 15:45:53 +01007859 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007860 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007861 else
7862 target = curproxy;
7863
7864 if (!target) {
7865 Alert("Proxy '%s': unable to find store table '%s'.\n",
7866 curproxy->id, mrule->table.name);
7867 cfgerr++;
7868 }
7869 else if (target->table.size == 0) {
7870 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7871 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7872 cfgerr++;
7873 }
Willy Tarreau12785782012-04-27 21:37:17 +02007874 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7875 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007876 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7877 cfgerr++;
7878 }
7879 else {
7880 free((void *)mrule->table.name);
7881 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007882 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007883 }
7884 }
7885
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007886 /* find the target table for 'tcp-request' layer 4 rules */
7887 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7888 struct proxy *target;
7889
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007890 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007891 continue;
7892
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007893 if (trule->arg.trk_ctr.table.n)
7894 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007895 else
7896 target = curproxy;
7897
7898 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007899 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007901 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007902 cfgerr++;
7903 }
7904 else if (target->table.size == 0) {
7905 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007906 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007907 cfgerr++;
7908 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007909 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007910 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007911 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007912 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007913 cfgerr++;
7914 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007915 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007916 free(trule->arg.trk_ctr.table.n);
7917 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007918 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007919 * to pass a list of counters to track and allocate them right here using
7920 * stktable_alloc_data_type().
7921 */
7922 }
7923 }
7924
Willy Tarreau620408f2016-10-21 16:37:51 +02007925 /* find the target table for 'tcp-request' layer 5 rules */
7926 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7927 struct proxy *target;
7928
7929 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7930 continue;
7931
7932 if (trule->arg.trk_ctr.table.n)
7933 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7934 else
7935 target = curproxy;
7936
7937 if (!target) {
7938 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7939 curproxy->id, trule->arg.trk_ctr.table.n,
7940 tcp_trk_idx(trule->action));
7941 cfgerr++;
7942 }
7943 else if (target->table.size == 0) {
7944 Alert("Proxy '%s': table '%s' used but not configured.\n",
7945 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7946 cfgerr++;
7947 }
7948 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7949 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7950 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7951 tcp_trk_idx(trule->action));
7952 cfgerr++;
7953 }
7954 else {
7955 free(trule->arg.trk_ctr.table.n);
7956 trule->arg.trk_ctr.table.t = &target->table;
7957 /* Note: if we decide to enhance the track-sc syntax, we may be able
7958 * to pass a list of counters to track and allocate them right here using
7959 * stktable_alloc_data_type().
7960 */
7961 }
7962 }
7963
Willy Tarreaud1f96522010-08-03 19:34:32 +02007964 /* find the target table for 'tcp-request' layer 6 rules */
7965 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7966 struct proxy *target;
7967
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007968 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007969 continue;
7970
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007971 if (trule->arg.trk_ctr.table.n)
7972 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007973 else
7974 target = curproxy;
7975
7976 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007977 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007978 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007979 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007980 cfgerr++;
7981 }
7982 else if (target->table.size == 0) {
7983 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007984 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007985 cfgerr++;
7986 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007987 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007988 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007989 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007990 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007991 cfgerr++;
7992 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007993 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007994 free(trule->arg.trk_ctr.table.n);
7995 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007996 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007997 * to pass a list of counters to track and allocate them right here using
7998 * stktable_alloc_data_type().
7999 */
8000 }
8001 }
8002
Baptiste Assmanne9544932015-11-03 23:31:35 +01008003 /* parse http-request capture rules to ensure id really exists */
8004 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8005 if (hrqrule->action != ACT_CUSTOM ||
8006 hrqrule->action_ptr != http_action_req_capture_by_id)
8007 continue;
8008
8009 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8010 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8011 curproxy->id, hrqrule->arg.capid.idx);
8012 cfgerr++;
8013 }
8014 }
8015
8016 /* parse http-response capture rules to ensure id really exists */
8017 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8018 if (hrqrule->action != ACT_CUSTOM ||
8019 hrqrule->action_ptr != http_action_res_capture_by_id)
8020 continue;
8021
8022 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8023 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8024 curproxy->id, hrqrule->arg.capid.idx);
8025 cfgerr++;
8026 }
8027 }
8028
Willy Tarreau09448f72014-06-25 18:12:15 +02008029 /* find the target table for 'http-request' layer 7 rules */
8030 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8031 struct proxy *target;
8032
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008033 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008034 continue;
8035
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008036 if (hrqrule->arg.trk_ctr.table.n)
8037 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008038 else
8039 target = curproxy;
8040
8041 if (!target) {
8042 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008043 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008044 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008045 cfgerr++;
8046 }
8047 else if (target->table.size == 0) {
8048 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008049 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008050 cfgerr++;
8051 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008052 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008053 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008054 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008055 http_trk_idx(hrqrule->action));
8056 cfgerr++;
8057 }
8058 else {
8059 free(hrqrule->arg.trk_ctr.table.n);
8060 hrqrule->arg.trk_ctr.table.t = &target->table;
8061 /* Note: if we decide to enhance the track-sc syntax, we may be able
8062 * to pass a list of counters to track and allocate them right here using
8063 * stktable_alloc_data_type().
8064 */
8065 }
8066 }
8067
8068 /* find the target table for 'http-response' layer 7 rules */
8069 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8070 struct proxy *target;
8071
8072 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8073 continue;
8074
8075 if (hrqrule->arg.trk_ctr.table.n)
8076 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8077 else
8078 target = curproxy;
8079
8080 if (!target) {
8081 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8082 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8083 http_trk_idx(hrqrule->action));
8084 cfgerr++;
8085 }
8086 else if (target->table.size == 0) {
8087 Alert("Proxy '%s': table '%s' used but not configured.\n",
8088 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8089 cfgerr++;
8090 }
8091 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8092 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8093 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8094 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008095 cfgerr++;
8096 }
8097 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008098 free(hrqrule->arg.trk_ctr.table.n);
8099 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008100 /* Note: if we decide to enhance the track-sc syntax, we may be able
8101 * to pass a list of counters to track and allocate them right here using
8102 * stktable_alloc_data_type().
8103 */
8104 }
8105 }
8106
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008107 /* move any "block" rules at the beginning of the http-request rules */
8108 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8109 /* insert block_rules into http_req_rules at the beginning */
8110 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8111 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8112 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8113 curproxy->http_req_rules.n = curproxy->block_rules.n;
8114 LIST_INIT(&curproxy->block_rules);
8115 }
8116
Emeric Brun32da3c42010-09-23 18:39:19 +02008117 if (curproxy->table.peers.name) {
8118 struct peers *curpeers = peers;
8119
8120 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8121 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8122 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008123 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008124 break;
8125 }
8126 }
8127
8128 if (!curpeers) {
8129 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8130 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008131 free((void *)curproxy->table.peers.name);
8132 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008133 cfgerr++;
8134 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008135 else if (curpeers->state == PR_STSTOPPED) {
8136 /* silently disable this peers section */
8137 curproxy->table.peers.p = NULL;
8138 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008139 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008140 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8141 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008142 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008143 cfgerr++;
8144 }
8145 }
8146
Simon Horman9dc49962015-01-30 11:22:59 +09008147
8148 if (curproxy->email_alert.mailers.name) {
8149 struct mailers *curmailers = mailers;
8150
8151 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8152 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8153 free(curproxy->email_alert.mailers.name);
8154 curproxy->email_alert.mailers.m = curmailers;
8155 curmailers->users++;
8156 break;
8157 }
8158 }
8159
8160 if (!curmailers) {
8161 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8162 curproxy->id, curproxy->email_alert.mailers.name);
8163 free_email_alert(curproxy);
8164 cfgerr++;
8165 }
8166 }
8167
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008168 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008169 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008170 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8171 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8172 "proxy", curproxy->id);
8173 cfgerr++;
8174 goto out_uri_auth_compat;
8175 }
8176
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008177 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008178 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008179 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008180 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008181
Willy Tarreau95fa4692010-02-01 13:05:50 +01008182 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8183 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008184
8185 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008186 uri_auth_compat_req[i++] = "realm";
8187 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8188 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008189
Willy Tarreau95fa4692010-02-01 13:05:50 +01008190 uri_auth_compat_req[i++] = "unless";
8191 uri_auth_compat_req[i++] = "{";
8192 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8193 uri_auth_compat_req[i++] = "}";
8194 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008195
Willy Tarreauff011f22011-01-06 17:51:27 +01008196 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8197 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008198 cfgerr++;
8199 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008200 }
8201
Willy Tarreauff011f22011-01-06 17:51:27 +01008202 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008203
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008204 if (curproxy->uri_auth->auth_realm) {
8205 free(curproxy->uri_auth->auth_realm);
8206 curproxy->uri_auth->auth_realm = NULL;
8207 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008208
8209 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008210 }
8211out_uri_auth_compat:
8212
Dragan Dosen43885c72015-10-01 13:18:13 +02008213 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008214 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008215 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8216 if (!curproxy->conf.logformat_sd_string) {
8217 /* set the default logformat_sd_string */
8218 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8219 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008220 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008221 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008222 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008223
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008224 /* compile the log format */
8225 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008226 if (curproxy->conf.logformat_string != default_http_log_format &&
8227 curproxy->conf.logformat_string != default_tcp_log_format &&
8228 curproxy->conf.logformat_string != clf_http_log_format)
8229 free(curproxy->conf.logformat_string);
8230 curproxy->conf.logformat_string = NULL;
8231 free(curproxy->conf.lfs_file);
8232 curproxy->conf.lfs_file = NULL;
8233 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008234
8235 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8236 free(curproxy->conf.logformat_sd_string);
8237 curproxy->conf.logformat_sd_string = NULL;
8238 free(curproxy->conf.lfsd_file);
8239 curproxy->conf.lfsd_file = NULL;
8240 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008241 }
8242
Willy Tarreau62a61232013-04-12 18:13:46 +02008243 if (curproxy->conf.logformat_string) {
8244 curproxy->conf.args.ctx = ARGC_LOG;
8245 curproxy->conf.args.file = curproxy->conf.lfs_file;
8246 curproxy->conf.args.line = curproxy->conf.lfs_line;
8247 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008248 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008249 curproxy->conf.args.file = NULL;
8250 curproxy->conf.args.line = 0;
8251 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008252
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008253 if (curproxy->conf.logformat_sd_string) {
8254 curproxy->conf.args.ctx = ARGC_LOGSD;
8255 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8256 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8257 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8258 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8259 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8260 curproxy->conf.args.file = NULL;
8261 curproxy->conf.args.line = 0;
8262 }
8263
Willy Tarreau62a61232013-04-12 18:13:46 +02008264 if (curproxy->conf.uniqueid_format_string) {
8265 curproxy->conf.args.ctx = ARGC_UIF;
8266 curproxy->conf.args.file = curproxy->conf.uif_file;
8267 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008268 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008269 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008270 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008271 curproxy->conf.args.file = NULL;
8272 curproxy->conf.args.line = 0;
8273 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008274
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008275 /* only now we can check if some args remain unresolved.
8276 * This must be done after the users and groups resolution.
8277 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008278 cfgerr += smp_resolve_args(curproxy);
8279 if (!cfgerr)
8280 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008281
Willy Tarreau2738a142006-07-08 17:28:09 +02008282 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008283 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008284 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008285 (!curproxy->timeout.connect ||
8286 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008287 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008288 " | While not properly invalid, you will certainly encounter various problems\n"
8289 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008290 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008291 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008292 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008293 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008294
Willy Tarreau1fa31262007-12-03 00:36:16 +01008295 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8296 * We must still support older configurations, so let's find out whether those
8297 * parameters have been set or must be copied from contimeouts.
8298 */
8299 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008300 if (!curproxy->timeout.tarpit ||
8301 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008302 /* tarpit timeout not set. We search in the following order:
8303 * default.tarpit, curr.connect, default.connect.
8304 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008305 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008306 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008307 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008308 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008309 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008310 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008311 }
8312 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008313 (!curproxy->timeout.queue ||
8314 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008315 /* queue timeout not set. We search in the following order:
8316 * default.queue, curr.connect, default.connect.
8317 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008318 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008319 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008320 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008321 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008322 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008323 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008324 }
8325 }
8326
Willy Tarreau1620ec32011-08-06 17:05:02 +02008327 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008328 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008329 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008330 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008331 }
8332
Willy Tarreau215663d2014-06-13 18:30:23 +02008333 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8334 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8335 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8336 proxy_type_str(curproxy), curproxy->id);
8337 err_code |= ERR_WARN;
8338 }
8339
Willy Tarreau193b8c62012-11-22 00:17:38 +01008340 /* ensure that cookie capture length is not too large */
8341 if (curproxy->capture_len >= global.tune.cookie_len) {
8342 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8343 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8344 err_code |= ERR_WARN;
8345 curproxy->capture_len = global.tune.cookie_len - 1;
8346 }
8347
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008348 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008349 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008350 curproxy->req_cap_pool = create_pool("ptrcap",
8351 curproxy->nb_req_cap * sizeof(char *),
8352 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008353 }
8354
8355 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008356 curproxy->rsp_cap_pool = create_pool("ptrcap",
8357 curproxy->nb_rsp_cap * sizeof(char *),
8358 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008359 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008360
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008361 switch (curproxy->load_server_state_from_file) {
8362 case PR_SRV_STATE_FILE_UNSPEC:
8363 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8364 break;
8365 case PR_SRV_STATE_FILE_GLOBAL:
8366 if (!global.server_state_file) {
8367 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",
8368 curproxy->id);
8369 err_code |= ERR_WARN;
8370 }
8371 break;
8372 }
8373
Willy Tarreaubaaee002006-06-26 02:48:02 +02008374 /* first, we will invert the servers list order */
8375 newsrv = NULL;
8376 while (curproxy->srv) {
8377 struct server *next;
8378
8379 next = curproxy->srv->next;
8380 curproxy->srv->next = newsrv;
8381 newsrv = curproxy->srv;
8382 if (!next)
8383 break;
8384 curproxy->srv = next;
8385 }
8386
Willy Tarreau17edc812014-01-03 12:14:34 +01008387 /* Check that no server name conflicts. This causes trouble in the stats.
8388 * We only emit a warning for the first conflict affecting each server,
8389 * in order to avoid combinatory explosion if all servers have the same
8390 * name. We do that only for servers which do not have an explicit ID,
8391 * because these IDs were made also for distinguishing them and we don't
8392 * want to annoy people who correctly manage them.
8393 */
8394 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8395 struct server *other_srv;
8396
8397 if (newsrv->puid)
8398 continue;
8399
8400 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8401 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8402 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8403 newsrv->conf.file, newsrv->conf.line,
8404 proxy_type_str(curproxy), curproxy->id,
8405 newsrv->id, other_srv->conf.line);
8406 break;
8407 }
8408 }
8409 }
8410
Willy Tarreaudd701652010-05-25 23:03:02 +02008411 /* assign automatic UIDs to servers which don't have one yet */
8412 next_id = 1;
8413 newsrv = curproxy->srv;
8414 while (newsrv != NULL) {
8415 if (!newsrv->puid) {
8416 /* server ID not set, use automatic numbering with first
8417 * spare entry starting with next_svid.
8418 */
8419 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8420 newsrv->conf.id.key = newsrv->puid = next_id;
8421 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8422 }
8423 next_id++;
8424 newsrv = newsrv->next;
8425 }
8426
Willy Tarreau20697042007-11-15 23:26:18 +01008427 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008428 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008429
Willy Tarreau62c3be22012-01-20 13:12:32 +01008430 /*
8431 * If this server supports a maxconn parameter, it needs a dedicated
8432 * tasks to fill the emptied slots when a connection leaves.
8433 * Also, resolve deferred tracking dependency if needed.
8434 */
8435 newsrv = curproxy->srv;
8436 while (newsrv != NULL) {
8437 if (newsrv->minconn > newsrv->maxconn) {
8438 /* Only 'minconn' was specified, or it was higher than or equal
8439 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8440 * this will avoid further useless expensive computations.
8441 */
8442 newsrv->maxconn = newsrv->minconn;
8443 } else if (newsrv->maxconn && !newsrv->minconn) {
8444 /* minconn was not specified, so we set it to maxconn */
8445 newsrv->minconn = newsrv->maxconn;
8446 }
8447
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008448#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008449 if (newsrv->use_ssl || newsrv->check.use_ssl)
8450 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008451#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008452
Willy Tarreau2f075e92013-12-03 11:11:34 +01008453 /* set the check type on the server */
8454 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8455
Willy Tarreau62c3be22012-01-20 13:12:32 +01008456 if (newsrv->trackit) {
8457 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008458 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008459 char *pname, *sname;
8460
8461 pname = newsrv->trackit;
8462 sname = strrchr(pname, '/');
8463
8464 if (sname)
8465 *sname++ = '\0';
8466 else {
8467 sname = pname;
8468 pname = NULL;
8469 }
8470
8471 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008472 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008473 if (!px) {
8474 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8475 proxy_type_str(curproxy), curproxy->id,
8476 newsrv->id, pname);
8477 cfgerr++;
8478 goto next_srv;
8479 }
8480 } else
8481 px = curproxy;
8482
8483 srv = findserver(px, sname);
8484 if (!srv) {
8485 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8486 proxy_type_str(curproxy), curproxy->id,
8487 newsrv->id, sname);
8488 cfgerr++;
8489 goto next_srv;
8490 }
8491
Willy Tarreau32091232014-05-16 13:52:00 +02008492 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8493 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8494 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008495 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008496 "tracking as it does not have any check nor agent enabled.\n",
8497 proxy_type_str(curproxy), curproxy->id,
8498 newsrv->id, px->id, srv->id);
8499 cfgerr++;
8500 goto next_srv;
8501 }
8502
8503 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8504
8505 if (loop) {
8506 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8507 "belongs to a tracking chain looping back to %s/%s.\n",
8508 proxy_type_str(curproxy), curproxy->id,
8509 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008510 cfgerr++;
8511 goto next_srv;
8512 }
8513
8514 if (curproxy != px &&
8515 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8516 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8517 "tracking: disable-on-404 option inconsistency.\n",
8518 proxy_type_str(curproxy), curproxy->id,
8519 newsrv->id, px->id, srv->id);
8520 cfgerr++;
8521 goto next_srv;
8522 }
8523
Willy Tarreau62c3be22012-01-20 13:12:32 +01008524 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008525 newsrv->tracknext = srv->trackers;
8526 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008527
8528 free(newsrv->trackit);
8529 newsrv->trackit = NULL;
8530 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008531
8532 /*
8533 * resolve server's resolvers name and update the resolvers pointer
8534 * accordingly
8535 */
8536 if (newsrv->resolvers_id) {
8537 struct dns_resolvers *curr_resolvers;
8538 int found;
8539
8540 found = 0;
8541 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8542 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8543 found = 1;
8544 break;
8545 }
8546 }
8547
8548 if (!found) {
8549 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8550 proxy_type_str(curproxy), curproxy->id,
8551 newsrv->id, newsrv->resolvers_id);
8552 cfgerr++;
8553 } else {
8554 free(newsrv->resolvers_id);
8555 newsrv->resolvers_id = NULL;
8556 if (newsrv->resolution)
8557 newsrv->resolution->resolvers = curr_resolvers;
8558 }
8559 }
8560 else {
8561 /* if no resolvers section associated to this server
8562 * we can clean up the associated resolution structure
8563 */
8564 if (newsrv->resolution) {
8565 free(newsrv->resolution->hostname_dn);
8566 newsrv->resolution->hostname_dn = NULL;
8567 free(newsrv->resolution);
8568 newsrv->resolution = NULL;
8569 }
8570 }
8571
Willy Tarreau62c3be22012-01-20 13:12:32 +01008572 next_srv:
8573 newsrv = newsrv->next;
8574 }
8575
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008576 /* We have to initialize the server lookup mechanism depending
8577 * on what LB algorithm was choosen.
8578 */
8579
8580 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8581 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8582 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008583 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8584 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8585 init_server_map(curproxy);
8586 } else {
8587 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8588 fwrr_init_server_groups(curproxy);
8589 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008590 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008591
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008592 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008593 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8594 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8595 fwlc_init_server_tree(curproxy);
8596 } else {
8597 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8598 fas_init_server_tree(curproxy);
8599 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008600 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008601
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008602 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008603 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8604 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8605 chash_init_server_tree(curproxy);
8606 } else {
8607 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8608 init_server_map(curproxy);
8609 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008610 break;
8611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008612
8613 if (curproxy->options & PR_O_LOGASAP)
8614 curproxy->to_log &= ~LW_BYTES;
8615
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008616 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008617 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8618 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008619 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8620 proxy_type_str(curproxy), curproxy->id);
8621 err_code |= ERR_WARN;
8622 }
8623
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008624 if (curproxy->mode != PR_MODE_HTTP) {
8625 int optnum;
8626
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008627 if (curproxy->uri_auth) {
8628 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8629 proxy_type_str(curproxy), curproxy->id);
8630 err_code |= ERR_WARN;
8631 curproxy->uri_auth = NULL;
8632 }
8633
Willy Tarreau87cf5142011-08-19 22:57:24 +02008634 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008635 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8636 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8637 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008638 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008639 }
8640
8641 if (curproxy->options & PR_O_ORGTO) {
8642 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8643 "originalto", proxy_type_str(curproxy), curproxy->id);
8644 err_code |= ERR_WARN;
8645 curproxy->options &= ~PR_O_ORGTO;
8646 }
8647
8648 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8649 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8650 (curproxy->cap & cfg_opts[optnum].cap) &&
8651 (curproxy->options & cfg_opts[optnum].val)) {
8652 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8653 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8654 err_code |= ERR_WARN;
8655 curproxy->options &= ~cfg_opts[optnum].val;
8656 }
8657 }
8658
8659 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8660 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8661 (curproxy->cap & cfg_opts2[optnum].cap) &&
8662 (curproxy->options2 & cfg_opts2[optnum].val)) {
8663 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8664 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8665 err_code |= ERR_WARN;
8666 curproxy->options2 &= ~cfg_opts2[optnum].val;
8667 }
8668 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008669
Willy Tarreau29fbe512015-08-20 19:35:14 +02008670#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008671 if (curproxy->conn_src.bind_hdr_occ) {
8672 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008673 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008674 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008675 err_code |= ERR_WARN;
8676 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008677#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008678 }
8679
Willy Tarreaubaaee002006-06-26 02:48:02 +02008680 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008681 * ensure that we're not cross-dressing a TCP server into HTTP.
8682 */
8683 newsrv = curproxy->srv;
8684 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008685 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008686 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8687 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008688 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008689 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008690
Willy Tarreau0cec3312011-10-31 13:49:26 +01008691 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8692 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8693 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8694 err_code |= ERR_WARN;
8695 }
8696
Willy Tarreauc93cd162014-05-13 15:54:22 +02008697 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008698 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8699 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8700 err_code |= ERR_WARN;
8701 }
8702
Willy Tarreau29fbe512015-08-20 19:35:14 +02008703#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008704 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8705 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008706 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 +01008707 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008708 err_code |= ERR_WARN;
8709 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008710#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008711 newsrv = newsrv->next;
8712 }
8713
Willy Tarreaue42bd962014-09-16 16:21:19 +02008714 /* check if we have a frontend with "tcp-request content" looking at L7
8715 * with no inspect-delay
8716 */
8717 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8718 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008719 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008720 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008721 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008722 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008723 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008724 break;
8725 }
8726
8727 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8728 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8729 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8730 " This means that these rules will randomly find their contents. This can be fixed by"
8731 " setting the tcp-request inspect-delay.\n",
8732 proxy_type_str(curproxy), curproxy->id);
8733 err_code |= ERR_WARN;
8734 }
8735 }
8736
Christopher Fauletd7c91962015-04-30 11:48:27 +02008737 /* Check filter configuration, if any */
8738 cfgerr += flt_check(curproxy);
8739
Willy Tarreauc1a21672009-08-16 22:37:44 +02008740 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008741 if (!curproxy->accept)
8742 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008743
Willy Tarreauc1a21672009-08-16 22:37:44 +02008744 if (curproxy->tcp_req.inspect_delay ||
8745 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008746 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008747
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008748 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008749 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008750 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008751 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008752
8753 /* both TCP and HTTP must check switching rules */
8754 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008755
8756 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008757 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008758 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8759 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008760 if (curproxy->mode == PR_MODE_HTTP) {
8761 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8762 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8763 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008764 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008765 }
8766
8767 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008768 if (curproxy->tcp_req.inspect_delay ||
8769 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8770 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8771
Emeric Brun97679e72010-09-23 17:56:44 +02008772 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8773 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8774
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008775 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008776 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008777 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008778 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008779
8780 /* If the backend does requires RDP cookie persistence, we have to
8781 * enable the corresponding analyser.
8782 */
8783 if (curproxy->options2 & PR_O2_RDPC_PRST)
8784 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008785
8786 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008787 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008788 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8789 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008790 if (curproxy->mode == PR_MODE_HTTP) {
8791 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8792 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8793 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008794 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008795 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008796 }
8797
8798 /***********************************************************/
8799 /* At this point, target names have already been resolved. */
8800 /***********************************************************/
8801
8802 /* Check multi-process mode compatibility */
8803
8804 if (global.nbproc > 1 && global.stats_fe) {
8805 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8806 unsigned long mask;
8807
8808 mask = nbits(global.nbproc);
8809 if (global.stats_fe->bind_proc)
8810 mask &= global.stats_fe->bind_proc;
8811
8812 if (bind_conf->bind_proc)
8813 mask &= bind_conf->bind_proc;
8814
8815 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008816 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008817 break;
8818 }
8819 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8820 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");
8821 }
8822 }
8823
8824 /* Make each frontend inherit bind-process from its listeners when not specified. */
8825 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8826 if (curproxy->bind_proc)
8827 continue;
8828
8829 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8830 unsigned long mask;
8831
Willy Tarreaue428b082015-05-04 21:57:58 +02008832 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008833 curproxy->bind_proc |= mask;
8834 }
8835
8836 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008837 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008838 }
8839
8840 if (global.stats_fe) {
8841 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8842 unsigned long mask;
8843
Cyril Bonté06181952016-02-24 00:14:54 +01008844 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008845 global.stats_fe->bind_proc |= mask;
8846 }
8847 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008848 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008849 }
8850
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008851 /* propagate bindings from frontends to backends. Don't do it if there
8852 * are any fatal errors as we must not call it with unresolved proxies.
8853 */
8854 if (!cfgerr) {
8855 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8856 if (curproxy->cap & PR_CAP_FE)
8857 propagate_processes(curproxy, NULL);
8858 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008859 }
8860
8861 /* Bind each unbound backend to all processes when not specified. */
8862 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8863 if (curproxy->bind_proc)
8864 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008865 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008866 }
8867
8868 /*******************************************************/
8869 /* At this step, all proxies have a non-null bind_proc */
8870 /*******************************************************/
8871
8872 /* perform the final checks before creating tasks */
8873
8874 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8875 struct listener *listener;
8876 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008877
Emeric Brunc52962f2012-11-15 18:28:02 +01008878#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008879 /* Configure SSL for each bind line.
8880 * Note: if configuration fails at some point, the ->ctx member
8881 * remains NULL so that listeners can later detach.
8882 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008883 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008884 int alloc_ctx;
8885
Emeric Brunc52962f2012-11-15 18:28:02 +01008886 if (!bind_conf->is_ssl) {
8887 if (bind_conf->default_ctx) {
8888 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8889 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8890 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008891 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008892 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008893 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008894 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008895 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008896 cfgerr++;
8897 continue;
8898 }
8899
Emeric Brun8dc60392014-05-09 13:52:00 +02008900 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008901 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008902 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8903 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");
8904 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008905 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008906 cfgerr++;
8907 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008908 }
8909
Emeric Brunfc0421f2012-09-07 17:30:07 +02008910 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008911 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008912
8913 /* initialize CA variables if the certificates generation is enabled */
8914 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008915 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008916#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008917
Willy Tarreaue6b98942007-10-29 01:09:36 +01008918 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008919 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008920 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008921 int nbproc;
8922
8923 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008924 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008925 nbits(global.nbproc));
8926
8927 if (!nbproc) /* no intersection between listener and frontend */
8928 nbproc = 1;
8929
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008930 if (!listener->luid) {
8931 /* listener ID not set, use automatic numbering with first
8932 * spare entry starting with next_luid.
8933 */
8934 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8935 listener->conf.id.key = listener->luid = next_id;
8936 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008937 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008938 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008939
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008940 /* enable separate counters */
8941 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008942 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008943 if (!listener->name)
8944 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008945 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008946
Willy Tarreaue6b98942007-10-29 01:09:36 +01008947 if (curproxy->options & PR_O_TCP_NOLING)
8948 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008949 if (!listener->maxconn)
8950 listener->maxconn = curproxy->maxconn;
8951 if (!listener->backlog)
8952 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008953 if (!listener->maxaccept)
8954 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8955
8956 /* we want to have an optimal behaviour on single process mode to
8957 * maximize the work at once, but in multi-process we want to keep
8958 * some fairness between processes, so we target half of the max
8959 * number of events to be balanced over all the processes the proxy
8960 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8961 * used to disable the limit.
8962 */
8963 if (listener->maxaccept > 0) {
8964 if (nbproc > 1)
8965 listener->maxaccept = (listener->maxaccept + 1) / 2;
8966 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8967 }
8968
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008969 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008970 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008971 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008972 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008973
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008974 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008975 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008976
Willy Tarreau620408f2016-10-21 16:37:51 +02008977 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8978 listener->options |= LI_O_TCP_L5_RULES;
8979
Willy Tarreaude3041d2010-05-31 10:56:17 +02008980 if (curproxy->mon_mask.s_addr)
8981 listener->options |= LI_O_CHK_MONNET;
8982
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008983 /* smart accept mode is automatic in HTTP mode */
8984 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008985 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008986 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8987 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008988 }
8989
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008990 /* Release unused SSL configs */
8991 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8992 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008993 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008994#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008995 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008996 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008997 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008998 free(bind_conf->ca_sign_file);
8999 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009000 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009001 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009002 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009003 if(bind_conf->keys_ref) {
9004 free(bind_conf->keys_ref->filename);
9005 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009006 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009007 free(bind_conf->keys_ref);
9008 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009009#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009010 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009011
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009012 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009013 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009014 int count, maxproc = 0;
9015
9016 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009017 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009018 if (count > maxproc)
9019 maxproc = count;
9020 }
9021 /* backends have 0, frontends have 1 or more */
9022 if (maxproc != 1)
9023 Warning("Proxy '%s': in multi-process mode, stats will be"
9024 " limited to process assigned to the current request.\n",
9025 curproxy->id);
9026
Willy Tarreau102df612014-05-07 23:56:38 +02009027 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9028 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9029 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009030 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009031 }
Willy Tarreau102df612014-05-07 23:56:38 +02009032 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9033 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9034 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009035 }
9036 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009037
9038 /* create the task associated with the proxy */
9039 curproxy->task = task_new();
9040 if (curproxy->task) {
9041 curproxy->task->context = curproxy;
9042 curproxy->task->process = manage_proxy;
9043 /* no need to queue, it will be done automatically if some
9044 * listener gets limited.
9045 */
9046 curproxy->task->expire = TICK_ETERNITY;
9047 } else {
9048 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9049 curproxy->id);
9050 cfgerr++;
9051 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009052 }
9053
Willy Tarreaufbb78422011-06-05 15:38:35 +02009054 /* automatically compute fullconn if not set. We must not do it in the
9055 * loop above because cross-references are not yet fully resolved.
9056 */
9057 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9058 /* If <fullconn> is not set, let's set it to 10% of the sum of
9059 * the possible incoming frontend's maxconns.
9060 */
9061 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9062 struct proxy *fe;
9063 int total = 0;
9064
9065 /* sum up the number of maxconns of frontends which
9066 * reference this backend at least once or which are
9067 * the same one ('listen').
9068 */
9069 for (fe = proxy; fe; fe = fe->next) {
9070 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009071 int found = 0;
9072
9073 if (!(fe->cap & PR_CAP_FE))
9074 continue;
9075
9076 if (fe == curproxy) /* we're on a "listen" instance */
9077 found = 1;
9078
9079 if (fe->defbe.be == curproxy) /* "default_backend" */
9080 found = 1;
9081
9082 /* check if a "use_backend" rule matches */
9083 if (!found) {
9084 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009085 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009086 found = 1;
9087 break;
9088 }
9089 }
9090 }
9091
Willy Tarreaufbb78422011-06-05 15:38:35 +02009092 /* now we've checked all possible ways to reference a backend
9093 * from a frontend.
9094 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009095 if (!found)
9096 continue;
9097 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009098 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009099 /* we have the sum of the maxconns in <total>. We only
9100 * keep 10% of that sum to set the default fullconn, with
9101 * a hard minimum of 1 (to avoid a divide by zero).
9102 */
9103 curproxy->fullconn = (total + 9) / 10;
9104 if (!curproxy->fullconn)
9105 curproxy->fullconn = 1;
9106 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009107 }
9108
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009109 /*
9110 * Recount currently required checks.
9111 */
9112
9113 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9114 int optnum;
9115
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009116 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9117 if (curproxy->options & cfg_opts[optnum].val)
9118 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009119
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009120 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9121 if (curproxy->options2 & cfg_opts2[optnum].val)
9122 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009123 }
9124
Willy Tarreau0fca4832015-05-01 19:12:05 +02009125 /* compute the required process bindings for the peers */
9126 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9127 if (curproxy->table.peers.p)
9128 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9129
Willy Tarreau122541c2011-09-07 21:24:49 +02009130 if (peers) {
9131 struct peers *curpeers = peers, **last;
9132 struct peer *p, *pb;
9133
Willy Tarreau1e273012015-05-01 19:15:17 +02009134 /* Remove all peers sections which don't have a valid listener,
9135 * which are not used by any table, or which are bound to more
9136 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009137 */
9138 last = &peers;
9139 while (*last) {
9140 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009141
9142 if (curpeers->state == PR_STSTOPPED) {
9143 /* the "disabled" keyword was present */
9144 if (curpeers->peers_fe)
9145 stop_proxy(curpeers->peers_fe);
9146 curpeers->peers_fe = NULL;
9147 }
9148 else if (!curpeers->peers_fe) {
9149 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9150 curpeers->id, localpeer);
9151 }
David Carliere6c39412015-07-02 07:00:17 +00009152 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009153 /* either it's totally stopped or too much used */
9154 if (curpeers->peers_fe->bind_proc) {
9155 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009156 "running in different processes (%d different ones). "
9157 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009158 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009159 cfgerr++;
9160 }
9161 stop_proxy(curpeers->peers_fe);
9162 curpeers->peers_fe = NULL;
9163 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009164 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009165 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009166 last = &curpeers->next;
9167 continue;
9168 }
9169
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009170 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009171 p = curpeers->remote;
9172 while (p) {
9173 pb = p->next;
9174 free(p->id);
9175 free(p);
9176 p = pb;
9177 }
9178
9179 /* Destroy and unlink this curpeers section.
9180 * Note: curpeers is backed up into *last.
9181 */
9182 free(curpeers->id);
9183 curpeers = curpeers->next;
9184 free(*last);
9185 *last = curpeers;
9186 }
9187 }
9188
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009189 /* initialize stick-tables on backend capable proxies. This must not
9190 * be done earlier because the data size may be discovered while parsing
9191 * other proxies.
9192 */
9193 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9194 if (curproxy->state == PR_STSTOPPED)
9195 continue;
9196
9197 if (!stktable_init(&curproxy->table)) {
9198 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9199 cfgerr++;
9200 }
9201 }
9202
Simon Horman0d16a402015-01-30 11:22:58 +09009203 if (mailers) {
9204 struct mailers *curmailers = mailers, **last;
9205 struct mailer *m, *mb;
9206
9207 /* Remove all mailers sections which don't have a valid listener.
9208 * This can happen when a mailers section is never referenced.
9209 */
9210 last = &mailers;
9211 while (*last) {
9212 curmailers = *last;
9213 if (curmailers->users) {
9214 last = &curmailers->next;
9215 continue;
9216 }
9217
9218 Warning("Removing incomplete section 'mailers %s'.\n",
9219 curmailers->id);
9220
9221 m = curmailers->mailer_list;
9222 while (m) {
9223 mb = m->next;
9224 free(m->id);
9225 free(m);
9226 m = mb;
9227 }
9228
9229 /* Destroy and unlink this curmailers section.
9230 * Note: curmailers is backed up into *last.
9231 */
9232 free(curmailers->id);
9233 curmailers = curmailers->next;
9234 free(*last);
9235 *last = curmailers;
9236 }
9237 }
9238
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009239 /* Update server_state_file_name to backend name if backend is supposed to use
9240 * a server-state file locally defined and none has been provided */
9241 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9242 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9243 curproxy->server_state_file_name == NULL)
9244 curproxy->server_state_file_name = strdup(curproxy->id);
9245 }
9246
Willy Tarreau34eb6712011-10-24 18:15:04 +02009247 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009248 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009249 MEM_F_SHARED);
9250
Willy Tarreaubb925012009-07-23 13:36:36 +02009251 if (cfgerr > 0)
9252 err_code |= ERR_ALERT | ERR_FATAL;
9253 out:
9254 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009255}
9256
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009257/*
9258 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9259 * parsing sessions.
9260 */
9261void cfg_register_keywords(struct cfg_kw_list *kwl)
9262{
9263 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9264}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009265
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009266/*
9267 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9268 */
9269void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9270{
9271 LIST_DEL(&kwl->list);
9272 LIST_INIT(&kwl->list);
9273}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009274
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009275/* this function register new section in the haproxy configuration file.
9276 * <section_name> is the name of this new section and <section_parser>
9277 * is the called parser. If two section declaration have the same name,
9278 * only the first declared is used.
9279 */
9280int cfg_register_section(char *section_name,
9281 int (*section_parser)(const char *, int, char **, int))
9282{
9283 struct cfg_section *cs;
9284
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009285 list_for_each_entry(cs, &sections, list) {
9286 if (strcmp(cs->section_name, section_name) == 0) {
9287 Alert("register section '%s': already registered.\n", section_name);
9288 return 0;
9289 }
9290 }
9291
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009292 cs = calloc(1, sizeof(*cs));
9293 if (!cs) {
9294 Alert("register section '%s': out of memory.\n", section_name);
9295 return 0;
9296 }
9297
9298 cs->section_name = section_name;
9299 cs->section_parser = section_parser;
9300
9301 LIST_ADDQ(&sections, &cs->list);
9302
9303 return 1;
9304}
9305
Willy Tarreaubaaee002006-06-26 02:48:02 +02009306/*
David Carlier845efb52015-09-25 11:49:18 +01009307 * free all config section entries
9308 */
9309void cfg_unregister_sections(void)
9310{
9311 struct cfg_section *cs, *ics;
9312
9313 list_for_each_entry_safe(cs, ics, &sections, list) {
9314 LIST_DEL(&cs->list);
9315 free(cs);
9316 }
9317}
9318
Christopher Faulet7110b402016-10-26 11:09:44 +02009319void cfg_backup_sections(struct list *backup_sections)
9320{
9321 struct cfg_section *cs, *ics;
9322
9323 list_for_each_entry_safe(cs, ics, &sections, list) {
9324 LIST_DEL(&cs->list);
9325 LIST_ADDQ(backup_sections, &cs->list);
9326 }
9327}
9328
9329void cfg_restore_sections(struct list *backup_sections)
9330{
9331 struct cfg_section *cs, *ics;
9332
9333 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9334 LIST_DEL(&cs->list);
9335 LIST_ADDQ(&sections, &cs->list);
9336 }
9337}
9338
Willy Tarreau659fbf02016-05-26 17:55:28 +02009339__attribute__((constructor))
9340static void cfgparse_init(void)
9341{
9342 /* Register internal sections */
9343 cfg_register_section("listen", cfg_parse_listen);
9344 cfg_register_section("frontend", cfg_parse_listen);
9345 cfg_register_section("backend", cfg_parse_listen);
9346 cfg_register_section("defaults", cfg_parse_listen);
9347 cfg_register_section("global", cfg_parse_global);
9348 cfg_register_section("userlist", cfg_parse_users);
9349 cfg_register_section("peers", cfg_parse_peers);
9350 cfg_register_section("mailers", cfg_parse_mailers);
9351 cfg_register_section("namespace_list", cfg_parse_netns);
9352 cfg_register_section("resolvers", cfg_parse_resolvers);
9353}
9354
David Carlier845efb52015-09-25 11:49:18 +01009355/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009356 * Local variables:
9357 * c-indent-level: 8
9358 * c-basic-offset: 8
9359 * End:
9360 */