blob: 7b05727a77f19ddec3679e4ec768f8da19856260 [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 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005121 else if (!strcmp(args[1], "spop-check")) {
5122 if (curproxy == &defproxy) {
5123 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5124 file, linenum, args[0], args[1]);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
5128 if (curproxy->cap & PR_CAP_FE) {
5129 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5130 file, linenum, args[0], args[1]);
5131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
5133 }
5134
5135 /* use SPOE request to check servers' health */
5136 free(curproxy->check_req);
5137 curproxy->check_req = NULL;
5138 curproxy->options2 &= ~PR_O2_CHK_ANY;
5139 curproxy->options2 |= PR_O2_SPOP_CHK;
5140
5141 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5142 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
5146 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5147 goto out;
5148 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005149 else if (!strcmp(args[1], "tcp-check")) {
5150 /* use raw TCPCHK send/expect to check servers' health */
5151 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5152 err_code |= ERR_WARN;
5153
5154 free(curproxy->check_req);
5155 curproxy->check_req = NULL;
5156 curproxy->options2 &= ~PR_O2_CHK_ANY;
5157 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005158 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5159 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005160 }
Simon Horman98637e52014-06-20 12:30:16 +09005161 else if (!strcmp(args[1], "external-check")) {
5162 /* excute an external command to check servers' health */
5163 free(curproxy->check_req);
5164 curproxy->check_req = NULL;
5165 curproxy->options2 &= ~PR_O2_CHK_ANY;
5166 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005167 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5168 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005169 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005170 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005171 int cur_arg;
5172
5173 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5174 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005175 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005176
Willy Tarreau87cf5142011-08-19 22:57:24 +02005177 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005178
5179 free(curproxy->fwdfor_hdr_name);
5180 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5181 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5182
5183 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5184 cur_arg = 2;
5185 while (*(args[cur_arg])) {
5186 if (!strcmp(args[cur_arg], "except")) {
5187 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005188 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005189 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5190 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005193 }
5194 /* flush useless bits */
5195 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005196 cur_arg += 2;
5197 } else if (!strcmp(args[cur_arg], "header")) {
5198 /* suboption header - needs additional argument for it */
5199 if (*(args[cur_arg+1]) == 0) {
5200 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5201 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005204 }
5205 free(curproxy->fwdfor_hdr_name);
5206 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5207 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5208 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005209 } else if (!strcmp(args[cur_arg], "if-none")) {
5210 curproxy->options &= ~PR_O_FF_ALWAYS;
5211 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005212 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005213 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005214 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005215 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005218 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005219 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005220 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005221 else if (!strcmp(args[1], "originalto")) {
5222 int cur_arg;
5223
5224 /* insert x-original-to field, but not for the IP address listed as an except.
5225 * set default options (ie: bitfield, header name, etc)
5226 */
5227
5228 curproxy->options |= PR_O_ORGTO;
5229
5230 free(curproxy->orgto_hdr_name);
5231 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5232 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5233
Willy Tarreau87cf5142011-08-19 22:57:24 +02005234 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005235 cur_arg = 2;
5236 while (*(args[cur_arg])) {
5237 if (!strcmp(args[cur_arg], "except")) {
5238 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005239 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 +02005240 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5241 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005244 }
5245 /* flush useless bits */
5246 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5247 cur_arg += 2;
5248 } else if (!strcmp(args[cur_arg], "header")) {
5249 /* suboption header - needs additional argument for it */
5250 if (*(args[cur_arg+1]) == 0) {
5251 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5252 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005255 }
5256 free(curproxy->orgto_hdr_name);
5257 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5258 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5259 cur_arg += 2;
5260 } else {
5261 /* unknown suboption - catchall */
5262 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5263 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005266 }
5267 } /* end while loop */
5268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 else {
5270 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005276 else if (!strcmp(args[0], "default_backend")) {
5277 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005279
5280 if (*(args[1]) == 0) {
5281 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005284 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005285 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005286 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005287
5288 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5289 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005293 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005294
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005295 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5296 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 +01005297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 /* enable reconnections to dispatch */
5300 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005301
5302 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005305 else if (!strcmp(args[0], "http-reuse")) {
5306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5307 err_code |= ERR_WARN;
5308
5309 if (strcmp(args[1], "never") == 0) {
5310 /* enable a graceful server shutdown on an HTTP 404 response */
5311 curproxy->options &= ~PR_O_REUSE_MASK;
5312 curproxy->options |= PR_O_REUSE_NEVR;
5313 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5314 goto out;
5315 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005316 else if (strcmp(args[1], "safe") == 0) {
5317 /* enable a graceful server shutdown on an HTTP 404 response */
5318 curproxy->options &= ~PR_O_REUSE_MASK;
5319 curproxy->options |= PR_O_REUSE_SAFE;
5320 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5321 goto out;
5322 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005323 else if (strcmp(args[1], "aggressive") == 0) {
5324 curproxy->options &= ~PR_O_REUSE_MASK;
5325 curproxy->options |= PR_O_REUSE_AGGR;
5326 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5327 goto out;
5328 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005329 else if (strcmp(args[1], "always") == 0) {
5330 /* enable a graceful server shutdown on an HTTP 404 response */
5331 curproxy->options &= ~PR_O_REUSE_MASK;
5332 curproxy->options |= PR_O_REUSE_ALWS;
5333 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5334 goto out;
5335 }
5336 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005337 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005342 else if (!strcmp(args[0], "http-check")) {
5343 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005344 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005345
5346 if (strcmp(args[1], "disable-on-404") == 0) {
5347 /* enable a graceful server shutdown on an HTTP 404 response */
5348 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005349 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5350 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005351 }
Willy Tarreauef781042010-01-27 11:53:01 +01005352 else if (strcmp(args[1], "send-state") == 0) {
5353 /* enable emission of the apparent state of a server in HTTP checks */
5354 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005355 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5356 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005357 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005358 else if (strcmp(args[1], "expect") == 0) {
5359 const char *ptr_arg;
5360 int cur_arg;
5361
5362 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5363 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367
5368 cur_arg = 2;
5369 /* consider exclamation marks, sole or at the beginning of a word */
5370 while (*(ptr_arg = args[cur_arg])) {
5371 while (*ptr_arg == '!') {
5372 curproxy->options2 ^= PR_O2_EXP_INV;
5373 ptr_arg++;
5374 }
5375 if (*ptr_arg)
5376 break;
5377 cur_arg++;
5378 }
5379 /* now ptr_arg points to the beginning of a word past any possible
5380 * exclamation mark, and cur_arg is the argument which holds this word.
5381 */
5382 if (strcmp(ptr_arg, "status") == 0) {
5383 if (!*(args[cur_arg + 1])) {
5384 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5385 file, linenum, args[0], args[1], ptr_arg);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005390 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005391 curproxy->expect_str = strdup(args[cur_arg + 1]);
5392 }
5393 else if (strcmp(ptr_arg, "string") == 0) {
5394 if (!*(args[cur_arg + 1])) {
5395 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5396 file, linenum, args[0], args[1], ptr_arg);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005401 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005402 curproxy->expect_str = strdup(args[cur_arg + 1]);
5403 }
5404 else if (strcmp(ptr_arg, "rstatus") == 0) {
5405 if (!*(args[cur_arg + 1])) {
5406 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5407 file, linenum, args[0], args[1], ptr_arg);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005412 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005413 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005414 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005415 free(curproxy->expect_regex);
5416 curproxy->expect_regex = NULL;
5417 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005418 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005419 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5420 error = NULL;
5421 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5422 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5423 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5424 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428 }
5429 else if (strcmp(ptr_arg, "rstring") == 0) {
5430 if (!*(args[cur_arg + 1])) {
5431 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5432 file, linenum, args[0], args[1], ptr_arg);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
5435 }
5436 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005437 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005438 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005439 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005440 free(curproxy->expect_regex);
5441 curproxy->expect_regex = NULL;
5442 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005443 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005444 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5445 error = NULL;
5446 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5447 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5448 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5449 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453 }
5454 else {
5455 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5456 file, linenum, args[0], args[1], ptr_arg);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
5460 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005461 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005462 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 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005465 }
5466 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005467 else if (!strcmp(args[0], "tcp-check")) {
5468 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5469 err_code |= ERR_WARN;
5470
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005471 if (strcmp(args[1], "comment") == 0) {
5472 int cur_arg;
5473 struct tcpcheck_rule *tcpcheck;
5474
5475 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005476 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005477 tcpcheck->action = TCPCHK_ACT_COMMENT;
5478
5479 if (!*args[cur_arg + 1]) {
5480 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5481 file, linenum, args[cur_arg]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
5485
5486 tcpcheck->comment = strdup(args[cur_arg + 1]);
5487
5488 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005489 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5490 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005491 }
5492 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005493 const char *ptr_arg;
5494 int cur_arg;
5495 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005496
5497 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005498 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5499 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5500 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5501 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5502 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005503
Willy Tarreau5581c272015-05-13 12:24:53 +02005504 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5505 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5506 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5507 file, linenum);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005510 }
5511
5512 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005513 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005514 tcpcheck->action = TCPCHK_ACT_CONNECT;
5515
5516 /* parsing each parameters to fill up the rule */
5517 while (*(ptr_arg = args[cur_arg])) {
5518 /* tcp port */
5519 if (strcmp(args[cur_arg], "port") == 0) {
5520 if ( (atol(args[cur_arg + 1]) > 65535) ||
5521 (atol(args[cur_arg + 1]) < 1) ){
5522 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5523 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527 tcpcheck->port = atol(args[cur_arg + 1]);
5528 cur_arg += 2;
5529 }
5530 /* send proxy protocol */
5531 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5532 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5533 cur_arg++;
5534 }
5535#ifdef USE_OPENSSL
5536 else if (strcmp(args[cur_arg], "ssl") == 0) {
5537 curproxy->options |= PR_O_TCPCHK_SSL;
5538 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5539 cur_arg++;
5540 }
5541#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005542 /* comment for this tcpcheck line */
5543 else if (strcmp(args[cur_arg], "comment") == 0) {
5544 if (!*args[cur_arg + 1]) {
5545 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5546 file, linenum, args[cur_arg]);
5547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
5550 tcpcheck->comment = strdup(args[cur_arg + 1]);
5551 cur_arg += 2;
5552 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005553 else {
5554#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005555 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 +01005556#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005557 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 +01005558#endif /* USE_OPENSSL */
5559 file, linenum, args[0], args[1], args[cur_arg]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563
5564 }
5565
5566 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5567 }
5568 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005569 if (! *(args[2]) ) {
5570 /* SEND string expected */
5571 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5572 file, linenum, args[0], args[1], args[2]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 } else {
5576 struct tcpcheck_rule *tcpcheck;
5577
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005578 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579
5580 tcpcheck->action = TCPCHK_ACT_SEND;
5581 tcpcheck->string_len = strlen(args[2]);
5582 tcpcheck->string = strdup(args[2]);
5583 tcpcheck->expect_regex = NULL;
5584
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005585 /* comment for this tcpcheck line */
5586 if (strcmp(args[3], "comment") == 0) {
5587 if (!*args[4]) {
5588 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5589 file, linenum, args[3]);
5590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
5592 }
5593 tcpcheck->comment = strdup(args[4]);
5594 }
5595
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005596 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5597 }
5598 }
5599 else if (strcmp(args[1], "send-binary") == 0) {
5600 if (! *(args[2]) ) {
5601 /* SEND binary string expected */
5602 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5603 file, linenum, args[0], args[1], args[2]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 } else {
5607 struct tcpcheck_rule *tcpcheck;
5608 char *err = NULL;
5609
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005610 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005611
5612 tcpcheck->action = TCPCHK_ACT_SEND;
5613 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5614 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5615 file, linenum, args[0], args[1], args[2], err);
5616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
5619 tcpcheck->expect_regex = NULL;
5620
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005621 /* comment for this tcpcheck line */
5622 if (strcmp(args[3], "comment") == 0) {
5623 if (!*args[4]) {
5624 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5625 file, linenum, args[3]);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629 tcpcheck->comment = strdup(args[4]);
5630 }
5631
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005632 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5633 }
5634 }
5635 else if (strcmp(args[1], "expect") == 0) {
5636 const char *ptr_arg;
5637 int cur_arg;
5638 int inverse = 0;
5639
5640 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5641 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
5645
5646 cur_arg = 2;
5647 /* consider exclamation marks, sole or at the beginning of a word */
5648 while (*(ptr_arg = args[cur_arg])) {
5649 while (*ptr_arg == '!') {
5650 inverse = !inverse;
5651 ptr_arg++;
5652 }
5653 if (*ptr_arg)
5654 break;
5655 cur_arg++;
5656 }
5657 /* now ptr_arg points to the beginning of a word past any possible
5658 * exclamation mark, and cur_arg is the argument which holds this word.
5659 */
5660 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005661 struct tcpcheck_rule *tcpcheck;
5662 char *err = NULL;
5663
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005664 if (!*(args[cur_arg + 1])) {
5665 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5666 file, linenum, args[0], args[1], ptr_arg);
5667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
5669 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005670
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005671 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005672
5673 tcpcheck->action = TCPCHK_ACT_EXPECT;
5674 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5675 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5676 file, linenum, args[0], args[1], args[2], err);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
5680 tcpcheck->expect_regex = NULL;
5681 tcpcheck->inverse = inverse;
5682
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005683 /* tcpcheck comment */
5684 cur_arg += 2;
5685 if (strcmp(args[cur_arg], "comment") == 0) {
5686 if (!*args[cur_arg + 1]) {
5687 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5688 file, linenum, args[cur_arg + 1]);
5689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
5691 }
5692 tcpcheck->comment = strdup(args[cur_arg + 1]);
5693 }
5694
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005695 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5696 }
5697 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005698 struct tcpcheck_rule *tcpcheck;
5699
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005700 if (!*(args[cur_arg + 1])) {
5701 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5702 file, linenum, args[0], args[1], ptr_arg);
5703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005706
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005707 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005708
5709 tcpcheck->action = TCPCHK_ACT_EXPECT;
5710 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5711 tcpcheck->string = strdup(args[cur_arg + 1]);
5712 tcpcheck->expect_regex = NULL;
5713 tcpcheck->inverse = inverse;
5714
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005715 /* tcpcheck comment */
5716 cur_arg += 2;
5717 if (strcmp(args[cur_arg], "comment") == 0) {
5718 if (!*args[cur_arg + 1]) {
5719 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5720 file, linenum, args[cur_arg + 1]);
5721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
5723 }
5724 tcpcheck->comment = strdup(args[cur_arg + 1]);
5725 }
5726
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005727 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5728 }
5729 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005730 struct tcpcheck_rule *tcpcheck;
5731
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005732 if (!*(args[cur_arg + 1])) {
5733 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5734 file, linenum, args[0], args[1], ptr_arg);
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005738
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005739 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005740
5741 tcpcheck->action = TCPCHK_ACT_EXPECT;
5742 tcpcheck->string_len = 0;
5743 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005744 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5745 error = NULL;
5746 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5747 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5748 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5749 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
5752 }
5753 tcpcheck->inverse = inverse;
5754
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005755 /* tcpcheck comment */
5756 cur_arg += 2;
5757 if (strcmp(args[cur_arg], "comment") == 0) {
5758 if (!*args[cur_arg + 1]) {
5759 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5760 file, linenum, args[cur_arg + 1]);
5761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
5763 }
5764 tcpcheck->comment = strdup(args[cur_arg + 1]);
5765 }
5766
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005767 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5768 }
5769 else {
5770 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5771 file, linenum, args[0], args[1], ptr_arg);
5772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775 }
5776 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005777 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
5780 }
5781 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005782 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005783 if (curproxy == &defproxy) {
5784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005787 }
5788
Willy Tarreaub80c2302007-11-30 20:51:32 +01005789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005791
5792 if (strcmp(args[1], "fail") == 0) {
5793 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005794 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005795 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5796 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005799 }
5800
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5802 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5803 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005806 }
5807 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5808 }
5809 else {
5810 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005813 }
5814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815#ifdef TPROXY
5816 else if (!strcmp(args[0], "transparent")) {
5817 /* enable transparent proxy connections */
5818 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005819 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 }
5822#endif
5823 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005824 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005826
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 if (*(args[1]) == 0) {
5828 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005829 err_code |= ERR_ALERT | ERR_FATAL;
5830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 }
5832 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005833 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005836 else if (!strcmp(args[0], "backlog")) { /* backlog */
5837 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005838 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005839
5840 if (*(args[1]) == 0) {
5841 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005844 }
5845 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005846 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5847 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005848 }
Willy Tarreau86034312006-12-29 00:10:33 +01005849 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005851 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005852
Willy Tarreau86034312006-12-29 00:10:33 +01005853 if (*(args[1]) == 0) {
5854 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005855 err_code |= ERR_ALERT | ERR_FATAL;
5856 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005857 }
5858 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005859 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5860 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5863 if (*(args[1]) == 0) {
5864 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005868 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5869 if (err) {
5870 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5871 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005874 }
5875 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005880 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005881 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005882 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005883
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 if (curproxy == &defproxy) {
5885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005889 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005891
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005892 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005893 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005894 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005895 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005896 goto out;
5897 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005898
5899 proto = protocol_by_family(sk->ss_family);
5900 if (!proto || !proto->connect) {
5901 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5902 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005903 err_code |= ERR_ALERT | ERR_FATAL;
5904 goto out;
5905 }
5906
5907 if (port1 != port2) {
5908 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5909 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005913
5914 if (!port1) {
5915 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5916 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
5919 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005920
William Lallemanddf1425a2015-04-28 20:17:49 +02005921 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5922 goto out;
5923
Willy Tarreaud5191e72010-02-09 20:50:45 +01005924 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005925 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
5927 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005928 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005929 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005930
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005931 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5932 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005937 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005938 /**
5939 * The syntax for hash-type config element is
5940 * hash-type {map-based|consistent} [[<algo>] avalanche]
5941 *
5942 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5943 */
5944 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005945
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005946 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5947 err_code |= ERR_WARN;
5948
5949 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005950 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5951 }
5952 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005953 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5954 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005955 else if (strcmp(args[1], "avalanche") == 0) {
5956 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]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005959 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005960 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005961 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
Bhaskar98634f02013-10-29 23:30:51 -04005965
5966 /* set the hash function to use */
5967 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005968 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005969 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005970
5971 /* if consistent with no argument, then avalanche modifier is also applied */
5972 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5973 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005974 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005975 /* set the hash function */
5976 if (!strcmp(args[2], "sdbm")) {
5977 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5978 }
5979 else if (!strcmp(args[2], "djb2")) {
5980 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005981 }
5982 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005983 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005984 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005985 else if (!strcmp(args[2], "crc32")) {
5986 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5987 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005988 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005989 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 -05005990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
5992 }
5993
5994 /* set the hash modifier */
5995 if (!strcmp(args[3], "avalanche")) {
5996 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5997 }
5998 else if (*args[3]) {
5999 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6000 err_code |= ERR_ALERT | ERR_FATAL;
6001 goto out;
6002 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006003 }
William Lallemanda73203e2012-03-12 12:48:57 +01006004 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006005 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6006 if (*(args[1]) == 0) {
6007 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
6010 }
6011 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6012 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6013 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6014 err_code |= ERR_ALERT | ERR_FATAL;
6015 goto out;
6016 }
6017 }
William Lallemanda73203e2012-03-12 12:48:57 +01006018 else if (strcmp(args[0], "unique-id-format") == 0) {
6019 if (!*(args[1])) {
6020 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
William Lallemand3203ff42012-11-11 17:30:56 +01006024 if (*(args[2])) {
6025 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6026 err_code |= ERR_ALERT | ERR_FATAL;
6027 goto out;
6028 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006029 free(curproxy->conf.uniqueid_format_string);
6030 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006031
Willy Tarreau62a61232013-04-12 18:13:46 +02006032 free(curproxy->conf.uif_file);
6033 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6034 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006035 }
William Lallemanda73203e2012-03-12 12:48:57 +01006036
6037 else if (strcmp(args[0], "unique-id-header") == 0) {
6038 if (!*(args[1])) {
6039 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6040 err_code |= ERR_ALERT | ERR_FATAL;
6041 goto out;
6042 }
6043 free(curproxy->header_unique_id);
6044 curproxy->header_unique_id = strdup(args[1]);
6045 }
6046
William Lallemand723b73a2012-02-08 16:37:49 +01006047 else if (strcmp(args[0], "log-format") == 0) {
6048 if (!*(args[1])) {
6049 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
William Lallemand3203ff42012-11-11 17:30:56 +01006053 if (*(args[2])) {
6054 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6055 err_code |= ERR_ALERT | ERR_FATAL;
6056 goto out;
6057 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006058
Willy Tarreau62a61232013-04-12 18:13:46 +02006059 if (curproxy->conf.logformat_string != default_http_log_format &&
6060 curproxy->conf.logformat_string != default_tcp_log_format &&
6061 curproxy->conf.logformat_string != clf_http_log_format)
6062 free(curproxy->conf.logformat_string);
6063 curproxy->conf.logformat_string = strdup(args[1]);
6064
6065 free(curproxy->conf.lfs_file);
6066 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6067 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006068
6069 /* get a chance to improve log-format error reporting by
6070 * reporting the correct line-number when possible.
6071 */
6072 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6073 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6074 file, linenum, curproxy->id);
6075 err_code |= ERR_WARN;
6076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006078 else if (!strcmp(args[0], "log-format-sd")) {
6079 if (!*(args[1])) {
6080 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
6084 if (*(args[2])) {
6085 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6086 err_code |= ERR_ALERT | ERR_FATAL;
6087 goto out;
6088 }
6089
6090 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6091 free(curproxy->conf.logformat_sd_string);
6092 curproxy->conf.logformat_sd_string = strdup(args[1]);
6093
6094 free(curproxy->conf.lfsd_file);
6095 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6096 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6097
6098 /* get a chance to improve log-format-sd error reporting by
6099 * reporting the correct line-number when possible.
6100 */
6101 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6102 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6103 file, linenum, curproxy->id);
6104 err_code |= ERR_WARN;
6105 }
6106 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006107 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6108 if (*(args[1]) == 0) {
6109 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
6112 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006113 chunk_destroy(&curproxy->log_tag);
6114 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006115 }
William Lallemand0f99e342011-10-12 17:50:54 +02006116 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6117 /* delete previous herited or defined syslog servers */
6118 struct logsrv *back;
6119
6120 if (*(args[1]) != 0) {
6121 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124 }
6125
William Lallemand723b73a2012-02-08 16:37:49 +01006126 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6127 LIST_DEL(&tmplogsrv->list);
6128 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006129 }
6130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006132 struct logsrv *logsrv;
6133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006135 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006136 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006137 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006138 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006139 LIST_INIT(&node->list);
6140 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 }
6143 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006144 struct sockaddr_storage *sk;
6145 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006146 int arg = 0;
6147 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006148
Vincent Bernat02779b62016-04-03 13:48:43 +02006149 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150
Willy Tarreau18324f52014-06-27 18:10:07 +02006151 /* just after the address, a length may be specified */
6152 if (strcmp(args[arg+2], "len") == 0) {
6153 len = atoi(args[arg+3]);
6154 if (len < 80 || len > 65535) {
6155 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6156 file, linenum, args[arg+3]);
6157 err_code |= ERR_ALERT | ERR_FATAL;
6158 goto out;
6159 }
6160 logsrv->maxlen = len;
6161
6162 /* skip these two args */
6163 arg += 2;
6164 }
6165 else
6166 logsrv->maxlen = MAX_SYSLOG_LEN;
6167
6168 if (logsrv->maxlen > global.max_syslog_len) {
6169 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006170 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6171 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6172 logline = my_realloc2(logline, global.max_syslog_len + 1);
6173 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006174 }
6175
Dragan Dosen1322d092015-09-22 16:05:32 +02006176 /* after the length, a format may be specified */
6177 if (strcmp(args[arg+2], "format") == 0) {
6178 logsrv->format = get_log_format(args[arg+3]);
6179 if (logsrv->format < 0) {
6180 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
6183 }
6184
6185 /* skip these two args */
6186 arg += 2;
6187 }
6188
William Lallemanddf1425a2015-04-28 20:17:49 +02006189 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6190 goto out;
6191
Willy Tarreau18324f52014-06-27 18:10:07 +02006192 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006193 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006194 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006195 err_code |= ERR_ALERT | ERR_FATAL;
6196 goto out;
6197
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
6199
William Lallemand0f99e342011-10-12 17:50:54 +02006200 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006201 if (*(args[arg+3])) {
6202 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006203 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006204 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006205 err_code |= ERR_ALERT | ERR_FATAL;
6206 goto out;
6207
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
6209 }
6210
William Lallemand0f99e342011-10-12 17:50:54 +02006211 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006212 if (*(args[arg+4])) {
6213 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006214 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006215 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006216 err_code |= ERR_ALERT | ERR_FATAL;
6217 goto out;
6218
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006219 }
6220 }
6221
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006222 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006223 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006224 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006225 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006226 goto out;
6227 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006228
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006229 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006230
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006231 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006232 if (port1 != port2) {
6233 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6234 file, linenum, args[0], args[1]);
6235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
6237 }
6238
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006239 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006240 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241 }
William Lallemand0f99e342011-10-12 17:50:54 +02006242
6243 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 }
6245 else {
6246 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6247 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006248 err_code |= ERR_ALERT | ERR_FATAL;
6249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 }
6251 }
6252 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006253 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006254 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006255 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006256 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006257
Willy Tarreau977b8e42006-12-29 14:19:17 +01006258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006260
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006262 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6263 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006267
6268 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006269 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6270 free(curproxy->conn_src.iface_name);
6271 curproxy->conn_src.iface_name = NULL;
6272 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006273
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006274 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006275 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006276 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006277 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 goto out;
6280 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281
6282 proto = protocol_by_family(sk->ss_family);
6283 if (!proto || !proto->connect) {
6284 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006285 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
6288 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006289
6290 if (port1 != port2) {
6291 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6292 file, linenum, args[0], args[1]);
6293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
6295 }
6296
Willy Tarreauef9a3602012-12-08 22:29:20 +01006297 curproxy->conn_src.source_addr = *sk;
6298 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299
6300 cur_arg = 2;
6301 while (*(args[cur_arg])) {
6302 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006303#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006304 if (!*args[cur_arg + 1]) {
6305 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6306 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006309 }
6310
6311 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006312 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6313 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006314 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006315 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6316 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006317 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6318 char *name, *end;
6319
6320 name = args[cur_arg+1] + 7;
6321 while (isspace(*name))
6322 name++;
6323
6324 end = name;
6325 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6326 end++;
6327
Willy Tarreauef9a3602012-12-08 22:29:20 +01006328 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6329 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6330 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6331 curproxy->conn_src.bind_hdr_len = end - name;
6332 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6333 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6334 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006335
6336 /* now look for an occurrence number */
6337 while (isspace(*end))
6338 end++;
6339 if (*end == ',') {
6340 end++;
6341 name = end;
6342 if (*end == '-')
6343 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006344 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006345 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006346 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006347 }
6348
Willy Tarreauef9a3602012-12-08 22:29:20 +01006349 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006350 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6351 " occurrences values smaller than %d.\n",
6352 file, linenum, MAX_HDR_HISTORY);
6353 err_code |= ERR_ALERT | ERR_FATAL;
6354 goto out;
6355 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006356 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006357 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006358
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006359 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006360 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006361 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006362 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006363 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006364 goto out;
6365 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006366
6367 proto = protocol_by_family(sk->ss_family);
6368 if (!proto || !proto->connect) {
6369 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6370 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006371 err_code |= ERR_ALERT | ERR_FATAL;
6372 goto out;
6373 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006374
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006375 if (port1 != port2) {
6376 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6377 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006378 err_code |= ERR_ALERT | ERR_FATAL;
6379 goto out;
6380 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006381 curproxy->conn_src.tproxy_addr = *sk;
6382 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006383 }
6384 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006385#else /* no TPROXY support */
6386 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006387 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006390#endif
6391 cur_arg += 2;
6392 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006393 }
6394
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006395 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6396#ifdef SO_BINDTODEVICE
6397 if (!*args[cur_arg + 1]) {
6398 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006400 err_code |= ERR_ALERT | ERR_FATAL;
6401 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006402 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006403 free(curproxy->conn_src.iface_name);
6404 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6405 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006406 global.last_checks |= LSTCHK_NETADM;
6407#else
6408 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6409 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006410 err_code |= ERR_ALERT | ERR_FATAL;
6411 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006412#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006413 cur_arg += 2;
6414 continue;
6415 }
6416 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006417 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006422 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6423 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6424 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006425 err_code |= ERR_ALERT | ERR_FATAL;
6426 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6431 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006432 err_code |= ERR_ALERT | ERR_FATAL;
6433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435
6436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006438 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
6442 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a 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_REMOVE, 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 Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006451 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006452 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006459 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006470 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
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 Tarreaub8750a82006-09-03 09:56:00 +02006476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006481 err_code |= ERR_ALERT | ERR_FATAL;
6482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484
6485 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006486 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006487 args[0], args[1], args[2], (const char **)args+3);
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 }
6491 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a 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_REMOVE, 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 Tarreaubaaee002006-06-26 02:48:02 +02006497 }
6498 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006500 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
6505 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006507 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006514 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006515 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006516 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006519 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006521 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006522 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006523 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006524 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006527 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006528
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 if (curproxy == &defproxy) {
6530 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006531 err_code |= ERR_ALERT | ERR_FATAL;
6532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006534 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006535 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 if (*(args[1]) == 0) {
6538 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006539 err_code |= ERR_ALERT | ERR_FATAL;
6540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006542
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006543 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006544 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6545 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6546 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006547 err_code |= ERR_ALERT | ERR_FATAL;
6548 goto out;
6549 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006550 err_code |= warnif_cond_conflicts(cond,
6551 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6552 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006553 }
6554 else if (*args[2]) {
6555 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6556 file, linenum, args[0], args[2]);
6557 err_code |= ERR_ALERT | ERR_FATAL;
6558 goto out;
6559 }
6560
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006561 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006562 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006563 wl->s = strdup(args[1]);
6564 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006565 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566 }
6567 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006574
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, 0,
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], "rspdel")) { /* delete response header from a regex */
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, 0,
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], "rspdeny")) { /* block response header from a regex */
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, 0,
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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006596 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006599 err_code |= ERR_ALERT | ERR_FATAL;
6600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 }
6602
Willy Tarreauade5ec42010-01-28 19:33:49 +01006603 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006604 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006605 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006606 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608 }
6609 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006610 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006611 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006612 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006613 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615 }
6616 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006617 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006618 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006619 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006620 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006622 }
6623 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006624 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006625
Willy Tarreaubaaee002006-06-26 02:48:02 +02006626 if (curproxy == &defproxy) {
6627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006630 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006631 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006632 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006633
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634 if (*(args[1]) == 0) {
6635 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006636 err_code |= ERR_ALERT | ERR_FATAL;
6637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006638 }
6639
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006640 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006641 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6642 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6643 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006644 err_code |= ERR_ALERT | ERR_FATAL;
6645 goto out;
6646 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006647 err_code |= warnif_cond_conflicts(cond,
6648 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6649 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006650 }
6651 else if (*args[2]) {
6652 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6653 file, linenum, args[0], args[2]);
6654 err_code |= ERR_ALERT | ERR_FATAL;
6655 goto out;
6656 }
6657
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006658 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006659 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006660 wl->s = strdup(args[1]);
6661 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006662 }
6663 else if (!strcmp(args[0], "errorloc") ||
6664 !strcmp(args[0], "errorloc302") ||
6665 !strcmp(args[0], "errorloc303")) { /* error location */
6666 int errnum, errlen;
6667 char *err;
6668
Willy Tarreau977b8e42006-12-29 14:19:17 +01006669 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006670 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006671
Willy Tarreaubaaee002006-06-26 02:48:02 +02006672 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006673 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006674 err_code |= ERR_ALERT | ERR_FATAL;
6675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006676 }
6677
6678 errnum = atol(args[1]);
6679 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006680 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6681 err = malloc(errlen);
6682 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006683 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006684 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6685 err = malloc(errlen);
6686 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687 }
6688
Willy Tarreau0f772532006-12-23 20:51:41 +01006689 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6690 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006691 chunk_destroy(&curproxy->errmsg[rc]);
6692 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006693 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006695 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006696
6697 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006698 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6699 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006700 free(err);
6701 }
6702 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006703 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6704 int errnum, errlen, fd;
6705 char *err;
6706 struct stat stat;
6707
6708 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006709 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006710
6711 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006712 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006713 err_code |= ERR_ALERT | ERR_FATAL;
6714 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006715 }
6716
6717 fd = open(args[2], O_RDONLY);
6718 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6719 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6720 file, linenum, args[2], args[1]);
6721 if (fd >= 0)
6722 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006723 err_code |= ERR_ALERT | ERR_FATAL;
6724 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006725 }
6726
Willy Tarreau27a674e2009-08-17 07:23:33 +02006727 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006728 errlen = stat.st_size;
6729 } else {
6730 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006731 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006732 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006733 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006734 }
6735
6736 err = malloc(errlen); /* malloc() must succeed during parsing */
6737 errnum = read(fd, err, errlen);
6738 if (errnum != errlen) {
6739 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6740 file, linenum, args[2], args[1]);
6741 close(fd);
6742 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006743 err_code |= ERR_ALERT | ERR_FATAL;
6744 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006745 }
6746 close(fd);
6747
6748 errnum = atol(args[1]);
6749 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6750 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006751 chunk_destroy(&curproxy->errmsg[rc]);
6752 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006753 break;
6754 }
6755 }
6756
6757 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006758 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6759 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006760 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006761 free(err);
6762 }
6763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006764 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006765 struct cfg_kw_list *kwl;
6766 int index;
6767
6768 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6769 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6770 if (kwl->kw[index].section != CFG_LISTEN)
6771 continue;
6772 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6773 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006774 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006775 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006776 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006777 err_code |= ERR_ALERT | ERR_FATAL;
6778 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006779 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006780 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006781 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006782 err_code |= ERR_WARN;
6783 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006784 }
Willy Tarreau93893792009-07-23 13:19:11 +02006785 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006786 }
6787 }
6788 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006789
Willy Tarreau6daf3432008-01-22 16:44:08 +01006790 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006791 err_code |= ERR_ALERT | ERR_FATAL;
6792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006793 }
Willy Tarreau93893792009-07-23 13:19:11 +02006794 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006795 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006796 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006797}
6798
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006800cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6801{
6802#ifdef CONFIG_HAP_NS
6803 const char *err;
6804 const char *item = args[0];
6805
6806 if (!strcmp(item, "namespace_list")) {
6807 return 0;
6808 }
6809 else if (!strcmp(item, "namespace")) {
6810 size_t idx = 1;
6811 const char *current;
6812 while (*(current = args[idx++])) {
6813 err = invalid_char(current);
6814 if (err) {
6815 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6816 file, linenum, *err, item, current);
6817 return ERR_ALERT | ERR_FATAL;
6818 }
6819
6820 if (netns_store_lookup(current, strlen(current))) {
6821 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6822 file, linenum, current);
6823 return ERR_ALERT | ERR_FATAL;
6824 }
6825 if (!netns_store_insert(current)) {
6826 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6827 file, linenum, current);
6828 return ERR_ALERT | ERR_FATAL;
6829 }
6830 }
6831 }
6832
6833 return 0;
6834#else
6835 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6836 file, linenum);
6837 return ERR_ALERT | ERR_FATAL;
6838#endif
6839}
6840
6841int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006842cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6843{
6844
6845 int err_code = 0;
6846 const char *err;
6847
6848 if (!strcmp(args[0], "userlist")) { /* new userlist */
6849 struct userlist *newul;
6850
6851 if (!*args[1]) {
6852 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6853 file, linenum, args[0]);
6854 err_code |= ERR_ALERT | ERR_FATAL;
6855 goto out;
6856 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6858 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006859
6860 err = invalid_char(args[1]);
6861 if (err) {
6862 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6863 file, linenum, *err, args[0], args[1]);
6864 err_code |= ERR_ALERT | ERR_FATAL;
6865 goto out;
6866 }
6867
6868 for (newul = userlist; newul; newul = newul->next)
6869 if (!strcmp(newul->name, args[1])) {
6870 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6871 file, linenum, args[1]);
6872 err_code |= ERR_WARN;
6873 goto out;
6874 }
6875
Vincent Bernat02779b62016-04-03 13:48:43 +02006876 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006877 if (!newul) {
6878 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6879 err_code |= ERR_ALERT | ERR_ABORT;
6880 goto out;
6881 }
6882
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006883 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006884 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006885 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6886 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006887 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888 goto out;
6889 }
6890
6891 newul->next = userlist;
6892 userlist = newul;
6893
6894 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006895 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006896 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006897 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898
6899 if (!*args[1]) {
6900 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6901 file, linenum, args[0]);
6902 err_code |= ERR_ALERT | ERR_FATAL;
6903 goto out;
6904 }
6905
6906 err = invalid_char(args[1]);
6907 if (err) {
6908 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6909 file, linenum, *err, args[0], args[1]);
6910 err_code |= ERR_ALERT | ERR_FATAL;
6911 goto out;
6912 }
6913
William Lallemand4ac9f542015-05-28 18:03:51 +02006914 if (!userlist)
6915 goto out;
6916
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006917 for (ag = userlist->groups; ag; ag = ag->next)
6918 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006919 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6920 file, linenum, args[1], userlist->name);
6921 err_code |= ERR_ALERT;
6922 goto out;
6923 }
6924
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006925 ag = calloc(1, sizeof(*ag));
6926 if (!ag) {
6927 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6928 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006929 goto out;
6930 }
6931
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006932 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006933 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006934 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6935 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006936 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006937 goto out;
6938 }
6939
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006940 cur_arg = 2;
6941
6942 while (*args[cur_arg]) {
6943 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006944 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006945 cur_arg += 2;
6946 continue;
6947 } else {
6948 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6949 file, linenum, args[0]);
6950 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006951 free(ag->groupusers);
6952 free(ag->name);
6953 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006954 goto out;
6955 }
6956 }
6957
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006958 ag->next = userlist->groups;
6959 userlist->groups = ag;
6960
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006961 } else if (!strcmp(args[0], "user")) { /* new user */
6962 struct auth_users *newuser;
6963 int cur_arg;
6964
6965 if (!*args[1]) {
6966 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6967 file, linenum, args[0]);
6968 err_code |= ERR_ALERT | ERR_FATAL;
6969 goto out;
6970 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006971 if (!userlist)
6972 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006973
6974 for (newuser = userlist->users; newuser; newuser = newuser->next)
6975 if (!strcmp(newuser->user, args[1])) {
6976 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6977 file, linenum, args[1], userlist->name);
6978 err_code |= ERR_ALERT;
6979 goto out;
6980 }
6981
Vincent Bernat02779b62016-04-03 13:48:43 +02006982 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006983 if (!newuser) {
6984 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6985 err_code |= ERR_ALERT | ERR_ABORT;
6986 goto out;
6987 }
6988
6989 newuser->user = strdup(args[1]);
6990
6991 newuser->next = userlist->users;
6992 userlist->users = newuser;
6993
6994 cur_arg = 2;
6995
6996 while (*args[cur_arg]) {
6997 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006998#ifdef CONFIG_HAP_CRYPT
6999 if (!crypt("", args[cur_arg + 1])) {
7000 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7001 file, linenum, newuser->user);
7002 err_code |= ERR_ALERT | ERR_FATAL;
7003 goto out;
7004 }
7005#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007006 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7007 file, linenum);
7008 err_code |= ERR_ALERT;
7009#endif
7010 newuser->pass = strdup(args[cur_arg + 1]);
7011 cur_arg += 2;
7012 continue;
7013 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7014 newuser->pass = strdup(args[cur_arg + 1]);
7015 newuser->flags |= AU_O_INSECURE;
7016 cur_arg += 2;
7017 continue;
7018 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007019 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007020 cur_arg += 2;
7021 continue;
7022 } else {
7023 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7024 file, linenum, args[0]);
7025 err_code |= ERR_ALERT | ERR_FATAL;
7026 goto out;
7027 }
7028 }
7029 } else {
7030 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7031 err_code |= ERR_ALERT | ERR_FATAL;
7032 }
7033
7034out:
7035 return err_code;
7036}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037
Christopher Faulet79bdef32016-11-04 22:36:15 +01007038int
7039cfg_parse_scope(const char *file, int linenum, char *line)
7040{
7041 char *beg, *end, *scope = NULL;
7042 int err_code = 0;
7043 const char *err;
7044
7045 beg = line + 1;
7046 end = strchr(beg, ']');
7047
7048 /* Detect end of scope declaration */
7049 if (!end || end == beg) {
7050 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7051 file, linenum);
7052 err_code |= ERR_ALERT | ERR_FATAL;
7053 goto out;
7054 }
7055
7056 /* Get scope name and check its validity */
7057 scope = my_strndup(beg, end-beg);
7058 err = invalid_char(scope);
7059 if (err) {
7060 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7061 file, linenum, *err);
7062 err_code |= ERR_ALERT | ERR_ABORT;
7063 goto out;
7064 }
7065
7066 /* Be sure to have a scope declaration alone on its line */
7067 line = end+1;
7068 while (isspace((unsigned char)*line))
7069 line++;
7070 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7071 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7072 file, linenum, *line);
7073 err_code |= ERR_ALERT | ERR_ABORT;
7074 goto out;
7075 }
7076
7077 /* We have a valid scope declaration, save it */
7078 free(cfg_scope);
7079 cfg_scope = scope;
7080 scope = NULL;
7081
7082 out:
7083 free(scope);
7084 return err_code;
7085}
7086
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087/*
7088 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007089 * Returns the error code, 0 if OK, or any combination of :
7090 * - ERR_ABORT: must abort ASAP
7091 * - ERR_FATAL: we can continue parsing but not start the service
7092 * - ERR_WARN: a warning has been emitted
7093 * - ERR_ALERT: an alert has been emitted
7094 * Only the two first ones can stop processing, the two others are just
7095 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007097int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007098{
William Lallemand64e84512015-05-12 14:25:37 +02007099 char *thisline;
7100 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 FILE *f;
7102 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007103 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007104 struct cfg_section *cs = NULL;
7105 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007106 int readbytes = 0;
7107
7108 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007109 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007110 return -1;
7111 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007112
David Carlier97880bb2016-04-08 10:35:26 +01007113 if ((f=fopen(file,"r")) == NULL) {
7114 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007115 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007117
William Lallemandb2f07452015-05-12 14:27:13 +02007118next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007119 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007120 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007121 char *end;
7122 char *args[MAX_LINE_ARGS + 1];
7123 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007124 int dquote = 0; /* double quote */
7125 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007126
Willy Tarreaubaaee002006-06-26 02:48:02 +02007127 linenum++;
7128
7129 end = line + strlen(line);
7130
William Lallemand64e84512015-05-12 14:25:37 +02007131 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007132 /* Check if we reached the limit and the last char is not \n.
7133 * Watch out for the last line without the terminating '\n'!
7134 */
William Lallemand64e84512015-05-12 14:25:37 +02007135 char *newline;
7136 int newlinesize = linesize * 2;
7137
7138 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7139 if (newline == NULL) {
7140 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7141 file, linenum);
7142 err_code |= ERR_ALERT | ERR_FATAL;
7143 continue;
7144 }
7145
7146 readbytes = linesize - 1;
7147 linesize = newlinesize;
7148 thisline = newline;
7149 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007150 }
7151
William Lallemand64e84512015-05-12 14:25:37 +02007152 readbytes = 0;
7153
Willy Tarreaubaaee002006-06-26 02:48:02 +02007154 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007155 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007156 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007157
Christopher Faulet79bdef32016-11-04 22:36:15 +01007158
7159 if (*line == '[') {/* This is the begining if a scope */
7160 err_code |= cfg_parse_scope(file, linenum, line);
7161 goto next_line;
7162 }
7163
Willy Tarreaubaaee002006-06-26 02:48:02 +02007164 arg = 0;
7165 args[arg] = line;
7166
7167 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007168 if (*line == '"' && !squote) { /* double quote outside single quotes */
7169 if (dquote)
7170 dquote = 0;
7171 else
7172 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007173 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007174 end--;
7175 }
7176 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7177 if (squote)
7178 squote = 0;
7179 else
7180 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007181 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007182 end--;
7183 }
7184 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007185 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7186 * C equivalent value. Other combinations left unchanged (eg: \1).
7187 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007188 int skip = 0;
7189 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7190 *line = line[1];
7191 skip = 1;
7192 }
7193 else if (line[1] == 'r') {
7194 *line = '\r';
7195 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007197 else if (line[1] == 'n') {
7198 *line = '\n';
7199 skip = 1;
7200 }
7201 else if (line[1] == 't') {
7202 *line = '\t';
7203 skip = 1;
7204 }
7205 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007206 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207 unsigned char hex1, hex2;
7208 hex1 = toupper(line[2]) - '0';
7209 hex2 = toupper(line[3]) - '0';
7210 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7211 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7212 *line = (hex1<<4) + hex2;
7213 skip = 3;
7214 }
7215 else {
7216 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007217 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007219 } else if (line[1] == '"') {
7220 *line = '"';
7221 skip = 1;
7222 } else if (line[1] == '\'') {
7223 *line = '\'';
7224 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007225 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7226 *line = '$';
7227 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007228 }
7229 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007230 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007231 end -= skip;
7232 }
7233 line++;
7234 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007235 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007236 /* end of string, end of loop */
7237 *line = 0;
7238 break;
7239 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007240 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007241 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007242 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007243 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007244 line++;
7245 args[++arg] = line;
7246 }
William Lallemandb2f07452015-05-12 14:27:13 +02007247 else if (dquote && *line == '$') {
7248 /* environment variables are evaluated inside double quotes */
7249 char *var_beg;
7250 char *var_end;
7251 char save_char;
7252 char *value;
7253 int val_len;
7254 int newlinesize;
7255 int braces = 0;
7256
7257 var_beg = line + 1;
7258 var_end = var_beg;
7259
7260 if (*var_beg == '{') {
7261 var_beg++;
7262 var_end++;
7263 braces = 1;
7264 }
7265
7266 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7267 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7268 err_code |= ERR_ALERT | ERR_FATAL;
7269 goto next_line; /* skip current line */
7270 }
7271
7272 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7273 var_end++;
7274
7275 save_char = *var_end;
7276 *var_end = '\0';
7277 value = getenv(var_beg);
7278 *var_end = save_char;
7279 val_len = value ? strlen(value) : 0;
7280
7281 if (braces) {
7282 if (*var_end == '}') {
7283 var_end++;
7284 braces = 0;
7285 } else {
7286 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7287 err_code |= ERR_ALERT | ERR_FATAL;
7288 goto next_line; /* skip current line */
7289 }
7290 }
7291
7292 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7293
7294 /* if not enough space in thisline */
7295 if (newlinesize > linesize) {
7296 char *newline;
7297
7298 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7299 if (newline == NULL) {
7300 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7301 err_code |= ERR_ALERT | ERR_FATAL;
7302 goto next_line; /* slip current line */
7303 }
7304 /* recompute pointers if realloc returns a new pointer */
7305 if (newline != thisline) {
7306 int i;
7307 int diff;
7308
7309 for (i = 0; i <= arg; i++) {
7310 diff = args[i] - thisline;
7311 args[i] = newline + diff;
7312 }
7313
7314 diff = var_end - thisline;
7315 var_end = newline + diff;
7316 diff = end - thisline;
7317 end = newline + diff;
7318 diff = line - thisline;
7319 line = newline + diff;
7320 thisline = newline;
7321 }
7322 linesize = newlinesize;
7323 }
7324
7325 /* insert value inside the line */
7326 memmove(line + val_len, var_end, end - var_end + 1);
7327 memcpy(line, value, val_len);
7328 end += val_len - (var_end - line);
7329 line += val_len;
7330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007331 else {
7332 line++;
7333 }
7334 }
William Lallemandb2f07452015-05-12 14:27:13 +02007335
William Lallemandf9873ba2015-05-05 17:37:14 +02007336 if (dquote) {
7337 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7338 err_code |= ERR_ALERT | ERR_FATAL;
7339 }
7340
7341 if (squote) {
7342 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7343 err_code |= ERR_ALERT | ERR_FATAL;
7344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007345
7346 /* empty line */
7347 if (!**args)
7348 continue;
7349
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007350 if (*line) {
7351 /* we had to stop due to too many args.
7352 * Let's terminate the string, print the offending part then cut the
7353 * last arg.
7354 */
7355 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7356 line++;
7357 *line = '\0';
7358
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007359 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007360 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007361 err_code |= ERR_ALERT | ERR_FATAL;
7362 args[arg] = line;
7363 }
7364
Willy Tarreau540abe42007-05-02 20:50:16 +02007365 /* zero out remaining args and ensure that at least one entry
7366 * is zeroed out.
7367 */
7368 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007369 args[arg] = line;
7370 }
7371
Willy Tarreau3842f002009-06-14 11:39:52 +02007372 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007373 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007374 char *tmp;
7375
Willy Tarreau3842f002009-06-14 11:39:52 +02007376 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007377 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007378 for (arg=0; *args[arg+1]; arg++)
7379 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007380 *tmp = '\0'; // fix the next arg to \0
7381 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007382 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007383 else if (!strcmp(args[0], "default")) {
7384 kwm = KWM_DEF;
7385 for (arg=0; *args[arg+1]; arg++)
7386 args[arg] = args[arg+1]; // shift args after inversion
7387 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007388
William Lallemand0f99e342011-10-12 17:50:54 +02007389 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7390 strcmp(args[0], "log") != 0) {
7391 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007392 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007393 }
7394
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007395 /* detect section start */
7396 list_for_each_entry(ics, &sections, list) {
7397 if (strcmp(args[0], ics->section_name) == 0) {
7398 cursection = ics->section_name;
7399 cs = ics;
7400 break;
7401 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007402 }
7403
Willy Tarreaubaaee002006-06-26 02:48:02 +02007404 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007405 if (cs)
7406 err_code |= cs->section_parser(file, linenum, args, kwm);
7407 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007408 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007410 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007411
7412 if (err_code & ERR_ABORT)
7413 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007414 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007415 free(cfg_scope);
7416 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007417 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007418 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007419 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007420 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007421}
7422
Willy Tarreau64ab6072014-09-16 12:17:36 +02007423/* This function propagates processes from frontend <from> to backend <to> so
7424 * that it is always guaranteed that a backend pointed to by a frontend is
7425 * bound to all of its processes. After that, if the target is a "listen"
7426 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007427 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007428 * checked first to ensure that <to> is already bound to all processes of
7429 * <from>, there is no risk of looping and we ensure to follow the shortest
7430 * path to the destination.
7431 *
7432 * It is possible to set <to> to NULL for the first call so that the function
7433 * takes care of visiting the initial frontend in <from>.
7434 *
7435 * It is important to note that the function relies on the fact that all names
7436 * have already been resolved.
7437 */
7438void propagate_processes(struct proxy *from, struct proxy *to)
7439{
7440 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007441
7442 if (to) {
7443 /* check whether we need to go down */
7444 if (from->bind_proc &&
7445 (from->bind_proc & to->bind_proc) == from->bind_proc)
7446 return;
7447
7448 if (!from->bind_proc && !to->bind_proc)
7449 return;
7450
7451 to->bind_proc = from->bind_proc ?
7452 (to->bind_proc | from->bind_proc) : 0;
7453
7454 /* now propagate down */
7455 from = to;
7456 }
7457
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007458 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007459 return;
7460
Willy Tarreauf6b70012014-12-18 14:00:43 +01007461 if (from->state == PR_STSTOPPED)
7462 return;
7463
Willy Tarreau64ab6072014-09-16 12:17:36 +02007464 /* default_backend */
7465 if (from->defbe.be)
7466 propagate_processes(from, from->defbe.be);
7467
7468 /* use_backend */
7469 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007470 if (rule->dynamic)
7471 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007472 to = rule->be.backend;
7473 propagate_processes(from, to);
7474 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007475}
7476
Willy Tarreaubb925012009-07-23 13:36:36 +02007477/*
7478 * Returns the error code, 0 if OK, or any combination of :
7479 * - ERR_ABORT: must abort ASAP
7480 * - ERR_FATAL: we can continue parsing but not start the service
7481 * - ERR_WARN: a warning has been emitted
7482 * - ERR_ALERT: an alert has been emitted
7483 * Only the two first ones can stop processing, the two others are just
7484 * indicators.
7485 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007486int check_config_validity()
7487{
7488 int cfgerr = 0;
7489 struct proxy *curproxy = NULL;
7490 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007491 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007492 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007493 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007494
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007495 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007496 /*
7497 * Now, check for the integrity of all that we have collected.
7498 */
7499
7500 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007501 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007502
Willy Tarreau193b8c62012-11-22 00:17:38 +01007503 if (!global.tune.max_http_hdr)
7504 global.tune.max_http_hdr = MAX_HTTP_HDR;
7505
7506 if (!global.tune.cookie_len)
7507 global.tune.cookie_len = CAPTURE_LEN;
7508
7509 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7510
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007511 /* Post initialisation of the users and groups lists. */
7512 err_code = userlist_postinit();
7513 if (err_code != ERR_NONE)
7514 goto out;
7515
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007516 /* first, we will invert the proxy list order */
7517 curproxy = NULL;
7518 while (proxy) {
7519 struct proxy *next;
7520
7521 next = proxy->next;
7522 proxy->next = curproxy;
7523 curproxy = proxy;
7524 if (!next)
7525 break;
7526 proxy = next;
7527 }
7528
Willy Tarreau419ead82014-09-16 13:41:21 +02007529 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007530 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007531 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007532 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007533 struct act_rule *trule;
7534 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007535 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007536 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007537 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007538
Willy Tarreau050536d2012-10-04 08:47:34 +02007539 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007540 /* proxy ID not set, use automatic numbering with first
7541 * spare entry starting with next_pxid.
7542 */
7543 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7544 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7545 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007546 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007547 next_pxid++;
7548
Willy Tarreau55ea7572007-06-17 19:56:27 +02007549
Willy Tarreaubaaee002006-06-26 02:48:02 +02007550 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007551 /* ensure we don't keep listeners uselessly bound */
7552 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007553 free((void *)curproxy->table.peers.name);
7554 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007555 continue;
7556 }
7557
Willy Tarreau102df612014-05-07 23:56:38 +02007558 /* Check multi-process mode compatibility for the current proxy */
7559
7560 if (curproxy->bind_proc) {
7561 /* an explicit bind-process was specified, let's check how many
7562 * processes remain.
7563 */
David Carliere6c39412015-07-02 07:00:17 +00007564 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007565
7566 curproxy->bind_proc &= nbits(global.nbproc);
7567 if (!curproxy->bind_proc && nbproc == 1) {
7568 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);
7569 curproxy->bind_proc = 1;
7570 }
7571 else if (!curproxy->bind_proc && nbproc > 1) {
7572 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);
7573 curproxy->bind_proc = 0;
7574 }
7575 }
7576
Willy Tarreau3d209582014-05-09 17:06:11 +02007577 /* check and reduce the bind-proc of each listener */
7578 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7579 unsigned long mask;
7580
7581 if (!bind_conf->bind_proc)
7582 continue;
7583
7584 mask = nbits(global.nbproc);
7585 if (curproxy->bind_proc)
7586 mask &= curproxy->bind_proc;
7587 /* mask cannot be null here thanks to the previous checks */
7588
David Carliere6c39412015-07-02 07:00:17 +00007589 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007590 bind_conf->bind_proc &= mask;
7591
7592 if (!bind_conf->bind_proc && nbproc == 1) {
7593 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",
7594 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7595 bind_conf->bind_proc = mask & ~(mask - 1);
7596 }
7597 else if (!bind_conf->bind_proc && nbproc > 1) {
7598 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",
7599 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7600 bind_conf->bind_proc = 0;
7601 }
7602 }
7603
Willy Tarreauff01a212009-03-15 13:46:16 +01007604 switch (curproxy->mode) {
7605 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007606 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007607 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007608 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007610 cfgerr++;
7611 }
7612
7613 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007614 Warning("config : servers will be ignored for %s '%s'.\n",
7615 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007616 break;
7617
7618 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007619 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007620 break;
7621
7622 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007623 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007624 break;
7625 }
7626
Willy Tarreauf3934b82015-08-11 11:36:45 +02007627 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7628 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7629 proxy_type_str(curproxy), curproxy->id);
7630 err_code |= ERR_WARN;
7631 }
7632
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007633 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007634 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007635 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007636 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7637 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007638 cfgerr++;
7639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007640#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007641 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007642 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7643 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007644 cfgerr++;
7645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007646#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007647 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007648 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7649 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007650 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007651 }
7652 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007653 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007654 /* If no LB algo is set in a backend, and we're not in
7655 * transparent mode, dispatch mode nor proxy mode, we
7656 * want to use balance roundrobin by default.
7657 */
7658 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7659 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007660 }
7661 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007662
Willy Tarreau1620ec32011-08-06 17:05:02 +02007663 if (curproxy->options & PR_O_DISPATCH)
7664 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7665 else if (curproxy->options & PR_O_HTTP_PROXY)
7666 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7667 else if (curproxy->options & PR_O_TRANSP)
7668 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007669
Willy Tarreau1620ec32011-08-06 17:05:02 +02007670 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7671 if (curproxy->options & PR_O_DISABLE404) {
7672 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7673 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7674 err_code |= ERR_WARN;
7675 curproxy->options &= ~PR_O_DISABLE404;
7676 }
7677 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7678 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7679 "send-state", proxy_type_str(curproxy), curproxy->id);
7680 err_code |= ERR_WARN;
7681 curproxy->options &= ~PR_O2_CHK_SNDST;
7682 }
Willy Tarreauef781042010-01-27 11:53:01 +01007683 }
7684
Simon Horman98637e52014-06-20 12:30:16 +09007685 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7686 if (!global.external_check) {
7687 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7688 curproxy->id, "option external-check");
7689 cfgerr++;
7690 }
7691 if (!curproxy->check_command) {
7692 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7693 curproxy->id, "option external-check");
7694 cfgerr++;
7695 }
7696 }
7697
Simon Horman64e34162015-02-06 11:11:57 +09007698 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007699 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7700 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007701 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7702 "'email-alert myhostname', or 'email-alert to' "
7703 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007704 "to be present).\n",
7705 proxy_type_str(curproxy), curproxy->id);
7706 err_code |= ERR_WARN;
7707 free_email_alert(curproxy);
7708 }
7709 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007710 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007711 }
7712
Simon Horman98637e52014-06-20 12:30:16 +09007713 if (curproxy->check_command) {
7714 int clear = 0;
7715 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7716 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7717 "external-check command", proxy_type_str(curproxy), curproxy->id);
7718 err_code |= ERR_WARN;
7719 clear = 1;
7720 }
7721 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007722 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007723 curproxy->id, "external-check command");
7724 cfgerr++;
7725 }
7726 if (clear) {
7727 free(curproxy->check_command);
7728 curproxy->check_command = NULL;
7729 }
7730 }
7731
7732 if (curproxy->check_path) {
7733 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7734 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7735 "external-check path", proxy_type_str(curproxy), curproxy->id);
7736 err_code |= ERR_WARN;
7737 free(curproxy->check_path);
7738 curproxy->check_path = NULL;
7739 }
7740 }
7741
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007742 /* if a default backend was specified, let's find it */
7743 if (curproxy->defbe.name) {
7744 struct proxy *target;
7745
Willy Tarreauafb39922015-05-26 12:04:09 +02007746 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007747 if (!target) {
7748 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7749 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007750 cfgerr++;
7751 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007752 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7753 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007754 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007755 } else if (target->mode != curproxy->mode &&
7756 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7757
7758 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7759 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7760 curproxy->conf.file, curproxy->conf.line,
7761 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7762 target->conf.file, target->conf.line);
7763 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007764 } else {
7765 free(curproxy->defbe.name);
7766 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007767
7768 /* Emit a warning if this proxy also has some servers */
7769 if (curproxy->srv) {
7770 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7771 curproxy->id);
7772 err_code |= ERR_WARN;
7773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007774 }
7775 }
7776
Willy Tarreau55ea7572007-06-17 19:56:27 +02007777 /* find the target proxy for 'use_backend' rules */
7778 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007779 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007780 struct logformat_node *node;
7781 char *pxname;
7782
7783 /* Try to parse the string as a log format expression. If the result
7784 * of the parsing is only one entry containing a simple string, then
7785 * it's a standard string corresponding to a static rule, thus the
7786 * parsing is cancelled and be.name is restored to be resolved.
7787 */
7788 pxname = rule->be.name;
7789 LIST_INIT(&rule->be.expr);
7790 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7791 curproxy->conf.args.file, curproxy->conf.args.line);
7792 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7793
7794 if (!LIST_ISEMPTY(&rule->be.expr)) {
7795 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7796 rule->dynamic = 1;
7797 free(pxname);
7798 continue;
7799 }
7800 /* simple string: free the expression and fall back to static rule */
7801 free(node->arg);
7802 free(node);
7803 }
7804
7805 rule->dynamic = 0;
7806 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007807
Willy Tarreauafb39922015-05-26 12:04:09 +02007808 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007809 if (!target) {
7810 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7811 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007812 cfgerr++;
7813 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007814 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7815 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007816 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007817 } else if (target->mode != curproxy->mode &&
7818 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7819
7820 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7821 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7822 curproxy->conf.file, curproxy->conf.line,
7823 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7824 target->conf.file, target->conf.line);
7825 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007826 } else {
7827 free((void *)rule->be.name);
7828 rule->be.backend = target;
7829 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007830 }
7831
Willy Tarreau64ab6072014-09-16 12:17:36 +02007832 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007833 list_for_each_entry(srule, &curproxy->server_rules, list) {
7834 struct server *target = findserver(curproxy, srule->srv.name);
7835
7836 if (!target) {
7837 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7838 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7839 cfgerr++;
7840 continue;
7841 }
7842 free((void *)srule->srv.name);
7843 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007844 }
7845
Emeric Brunb982a3d2010-01-04 15:45:53 +01007846 /* find the target table for 'stick' rules */
7847 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7848 struct proxy *target;
7849
Emeric Brun1d33b292010-01-04 15:47:17 +01007850 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7851 if (mrule->flags & STK_IS_STORE)
7852 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7853
Emeric Brunb982a3d2010-01-04 15:45:53 +01007854 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007855 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007856 else
7857 target = curproxy;
7858
7859 if (!target) {
7860 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7861 curproxy->id, mrule->table.name);
7862 cfgerr++;
7863 }
7864 else if (target->table.size == 0) {
7865 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7866 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7867 cfgerr++;
7868 }
Willy Tarreau12785782012-04-27 21:37:17 +02007869 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7870 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007871 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7872 cfgerr++;
7873 }
7874 else {
7875 free((void *)mrule->table.name);
7876 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007877 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007878 }
7879 }
7880
7881 /* find the target table for 'store response' rules */
7882 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7883 struct proxy *target;
7884
Emeric Brun1d33b292010-01-04 15:47:17 +01007885 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7886
Emeric Brunb982a3d2010-01-04 15:45:53 +01007887 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007888 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007889 else
7890 target = curproxy;
7891
7892 if (!target) {
7893 Alert("Proxy '%s': unable to find store table '%s'.\n",
7894 curproxy->id, mrule->table.name);
7895 cfgerr++;
7896 }
7897 else if (target->table.size == 0) {
7898 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7899 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7900 cfgerr++;
7901 }
Willy Tarreau12785782012-04-27 21:37:17 +02007902 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7903 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007904 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7905 cfgerr++;
7906 }
7907 else {
7908 free((void *)mrule->table.name);
7909 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007910 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007911 }
7912 }
7913
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007914 /* find the target table for 'tcp-request' layer 4 rules */
7915 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7916 struct proxy *target;
7917
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007918 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007919 continue;
7920
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007921 if (trule->arg.trk_ctr.table.n)
7922 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007923 else
7924 target = curproxy;
7925
7926 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007927 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007928 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007929 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007930 cfgerr++;
7931 }
7932 else if (target->table.size == 0) {
7933 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007934 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007935 cfgerr++;
7936 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007937 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007938 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007939 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007940 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007941 cfgerr++;
7942 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007943 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007944 free(trule->arg.trk_ctr.table.n);
7945 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007946 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007947 * to pass a list of counters to track and allocate them right here using
7948 * stktable_alloc_data_type().
7949 */
7950 }
7951 }
7952
Willy Tarreau620408f2016-10-21 16:37:51 +02007953 /* find the target table for 'tcp-request' layer 5 rules */
7954 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7955 struct proxy *target;
7956
7957 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7958 continue;
7959
7960 if (trule->arg.trk_ctr.table.n)
7961 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7962 else
7963 target = curproxy;
7964
7965 if (!target) {
7966 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7967 curproxy->id, trule->arg.trk_ctr.table.n,
7968 tcp_trk_idx(trule->action));
7969 cfgerr++;
7970 }
7971 else if (target->table.size == 0) {
7972 Alert("Proxy '%s': table '%s' used but not configured.\n",
7973 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7974 cfgerr++;
7975 }
7976 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7977 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7978 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7979 tcp_trk_idx(trule->action));
7980 cfgerr++;
7981 }
7982 else {
7983 free(trule->arg.trk_ctr.table.n);
7984 trule->arg.trk_ctr.table.t = &target->table;
7985 /* Note: if we decide to enhance the track-sc syntax, we may be able
7986 * to pass a list of counters to track and allocate them right here using
7987 * stktable_alloc_data_type().
7988 */
7989 }
7990 }
7991
Willy Tarreaud1f96522010-08-03 19:34:32 +02007992 /* find the target table for 'tcp-request' layer 6 rules */
7993 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7994 struct proxy *target;
7995
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007996 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007997 continue;
7998
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007999 if (trule->arg.trk_ctr.table.n)
8000 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008001 else
8002 target = curproxy;
8003
8004 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02008005 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008006 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008007 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02008008 cfgerr++;
8009 }
8010 else if (target->table.size == 0) {
8011 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008012 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008013 cfgerr++;
8014 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008015 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01008016 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008017 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008018 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01008019 cfgerr++;
8020 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008021 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008022 free(trule->arg.trk_ctr.table.n);
8023 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02008024 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02008025 * to pass a list of counters to track and allocate them right here using
8026 * stktable_alloc_data_type().
8027 */
8028 }
8029 }
8030
Baptiste Assmanne9544932015-11-03 23:31:35 +01008031 /* parse http-request capture rules to ensure id really exists */
8032 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8033 if (hrqrule->action != ACT_CUSTOM ||
8034 hrqrule->action_ptr != http_action_req_capture_by_id)
8035 continue;
8036
8037 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8038 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8039 curproxy->id, hrqrule->arg.capid.idx);
8040 cfgerr++;
8041 }
8042 }
8043
8044 /* parse http-response capture rules to ensure id really exists */
8045 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8046 if (hrqrule->action != ACT_CUSTOM ||
8047 hrqrule->action_ptr != http_action_res_capture_by_id)
8048 continue;
8049
8050 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8051 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8052 curproxy->id, hrqrule->arg.capid.idx);
8053 cfgerr++;
8054 }
8055 }
8056
Willy Tarreau09448f72014-06-25 18:12:15 +02008057 /* find the target table for 'http-request' layer 7 rules */
8058 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8059 struct proxy *target;
8060
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008061 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008062 continue;
8063
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008064 if (hrqrule->arg.trk_ctr.table.n)
8065 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008066 else
8067 target = curproxy;
8068
8069 if (!target) {
8070 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008071 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008072 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008073 cfgerr++;
8074 }
8075 else if (target->table.size == 0) {
8076 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008077 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008078 cfgerr++;
8079 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008080 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008081 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008082 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008083 http_trk_idx(hrqrule->action));
8084 cfgerr++;
8085 }
8086 else {
8087 free(hrqrule->arg.trk_ctr.table.n);
8088 hrqrule->arg.trk_ctr.table.t = &target->table;
8089 /* Note: if we decide to enhance the track-sc syntax, we may be able
8090 * to pass a list of counters to track and allocate them right here using
8091 * stktable_alloc_data_type().
8092 */
8093 }
8094 }
8095
8096 /* find the target table for 'http-response' layer 7 rules */
8097 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8098 struct proxy *target;
8099
8100 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8101 continue;
8102
8103 if (hrqrule->arg.trk_ctr.table.n)
8104 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8105 else
8106 target = curproxy;
8107
8108 if (!target) {
8109 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8110 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8111 http_trk_idx(hrqrule->action));
8112 cfgerr++;
8113 }
8114 else if (target->table.size == 0) {
8115 Alert("Proxy '%s': table '%s' used but not configured.\n",
8116 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8117 cfgerr++;
8118 }
8119 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8120 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8121 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8122 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008123 cfgerr++;
8124 }
8125 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008126 free(hrqrule->arg.trk_ctr.table.n);
8127 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008128 /* Note: if we decide to enhance the track-sc syntax, we may be able
8129 * to pass a list of counters to track and allocate them right here using
8130 * stktable_alloc_data_type().
8131 */
8132 }
8133 }
8134
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008135 /* move any "block" rules at the beginning of the http-request rules */
8136 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8137 /* insert block_rules into http_req_rules at the beginning */
8138 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8139 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8140 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8141 curproxy->http_req_rules.n = curproxy->block_rules.n;
8142 LIST_INIT(&curproxy->block_rules);
8143 }
8144
Emeric Brun32da3c42010-09-23 18:39:19 +02008145 if (curproxy->table.peers.name) {
8146 struct peers *curpeers = peers;
8147
8148 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8149 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8150 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008151 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008152 break;
8153 }
8154 }
8155
8156 if (!curpeers) {
8157 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8158 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008159 free((void *)curproxy->table.peers.name);
8160 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008161 cfgerr++;
8162 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008163 else if (curpeers->state == PR_STSTOPPED) {
8164 /* silently disable this peers section */
8165 curproxy->table.peers.p = NULL;
8166 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008167 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008168 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8169 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008170 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008171 cfgerr++;
8172 }
8173 }
8174
Simon Horman9dc49962015-01-30 11:22:59 +09008175
8176 if (curproxy->email_alert.mailers.name) {
8177 struct mailers *curmailers = mailers;
8178
8179 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8180 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8181 free(curproxy->email_alert.mailers.name);
8182 curproxy->email_alert.mailers.m = curmailers;
8183 curmailers->users++;
8184 break;
8185 }
8186 }
8187
8188 if (!curmailers) {
8189 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8190 curproxy->id, curproxy->email_alert.mailers.name);
8191 free_email_alert(curproxy);
8192 cfgerr++;
8193 }
8194 }
8195
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008196 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008197 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008198 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8199 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8200 "proxy", curproxy->id);
8201 cfgerr++;
8202 goto out_uri_auth_compat;
8203 }
8204
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008205 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008206 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008207 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008208 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008209
Willy Tarreau95fa4692010-02-01 13:05:50 +01008210 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8211 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008212
8213 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008214 uri_auth_compat_req[i++] = "realm";
8215 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8216 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008217
Willy Tarreau95fa4692010-02-01 13:05:50 +01008218 uri_auth_compat_req[i++] = "unless";
8219 uri_auth_compat_req[i++] = "{";
8220 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8221 uri_auth_compat_req[i++] = "}";
8222 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008223
Willy Tarreauff011f22011-01-06 17:51:27 +01008224 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8225 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008226 cfgerr++;
8227 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008228 }
8229
Willy Tarreauff011f22011-01-06 17:51:27 +01008230 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008231
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008232 if (curproxy->uri_auth->auth_realm) {
8233 free(curproxy->uri_auth->auth_realm);
8234 curproxy->uri_auth->auth_realm = NULL;
8235 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008236
8237 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008238 }
8239out_uri_auth_compat:
8240
Dragan Dosen43885c72015-10-01 13:18:13 +02008241 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008242 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008243 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8244 if (!curproxy->conf.logformat_sd_string) {
8245 /* set the default logformat_sd_string */
8246 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8247 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008248 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008249 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008250 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008251
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008252 /* compile the log format */
8253 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008254 if (curproxy->conf.logformat_string != default_http_log_format &&
8255 curproxy->conf.logformat_string != default_tcp_log_format &&
8256 curproxy->conf.logformat_string != clf_http_log_format)
8257 free(curproxy->conf.logformat_string);
8258 curproxy->conf.logformat_string = NULL;
8259 free(curproxy->conf.lfs_file);
8260 curproxy->conf.lfs_file = NULL;
8261 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008262
8263 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8264 free(curproxy->conf.logformat_sd_string);
8265 curproxy->conf.logformat_sd_string = NULL;
8266 free(curproxy->conf.lfsd_file);
8267 curproxy->conf.lfsd_file = NULL;
8268 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008269 }
8270
Willy Tarreau62a61232013-04-12 18:13:46 +02008271 if (curproxy->conf.logformat_string) {
8272 curproxy->conf.args.ctx = ARGC_LOG;
8273 curproxy->conf.args.file = curproxy->conf.lfs_file;
8274 curproxy->conf.args.line = curproxy->conf.lfs_line;
8275 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008276 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008277 curproxy->conf.args.file = NULL;
8278 curproxy->conf.args.line = 0;
8279 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008280
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008281 if (curproxy->conf.logformat_sd_string) {
8282 curproxy->conf.args.ctx = ARGC_LOGSD;
8283 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8284 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8285 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8286 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8287 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8288 curproxy->conf.args.file = NULL;
8289 curproxy->conf.args.line = 0;
8290 }
8291
Willy Tarreau62a61232013-04-12 18:13:46 +02008292 if (curproxy->conf.uniqueid_format_string) {
8293 curproxy->conf.args.ctx = ARGC_UIF;
8294 curproxy->conf.args.file = curproxy->conf.uif_file;
8295 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008296 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008297 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008298 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008299 curproxy->conf.args.file = NULL;
8300 curproxy->conf.args.line = 0;
8301 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008302
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008303 /* only now we can check if some args remain unresolved.
8304 * This must be done after the users and groups resolution.
8305 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008306 cfgerr += smp_resolve_args(curproxy);
8307 if (!cfgerr)
8308 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008309
Willy Tarreau2738a142006-07-08 17:28:09 +02008310 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008311 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008312 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008313 (!curproxy->timeout.connect ||
8314 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008315 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008316 " | While not properly invalid, you will certainly encounter various problems\n"
8317 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008318 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008319 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008320 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008321 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008322
Willy Tarreau1fa31262007-12-03 00:36:16 +01008323 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8324 * We must still support older configurations, so let's find out whether those
8325 * parameters have been set or must be copied from contimeouts.
8326 */
8327 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008328 if (!curproxy->timeout.tarpit ||
8329 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008330 /* tarpit timeout not set. We search in the following order:
8331 * default.tarpit, curr.connect, default.connect.
8332 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008333 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008334 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008335 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008336 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008337 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008338 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008339 }
8340 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008341 (!curproxy->timeout.queue ||
8342 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008343 /* queue timeout not set. We search in the following order:
8344 * default.queue, curr.connect, default.connect.
8345 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008346 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008347 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008348 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008349 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008350 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008351 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008352 }
8353 }
8354
Willy Tarreau1620ec32011-08-06 17:05:02 +02008355 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008356 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008357 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008358 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008359 }
8360
Willy Tarreau215663d2014-06-13 18:30:23 +02008361 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8362 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8363 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8364 proxy_type_str(curproxy), curproxy->id);
8365 err_code |= ERR_WARN;
8366 }
8367
Willy Tarreau193b8c62012-11-22 00:17:38 +01008368 /* ensure that cookie capture length is not too large */
8369 if (curproxy->capture_len >= global.tune.cookie_len) {
8370 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8371 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8372 err_code |= ERR_WARN;
8373 curproxy->capture_len = global.tune.cookie_len - 1;
8374 }
8375
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008376 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008377 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008378 curproxy->req_cap_pool = create_pool("ptrcap",
8379 curproxy->nb_req_cap * sizeof(char *),
8380 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008381 }
8382
8383 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008384 curproxy->rsp_cap_pool = create_pool("ptrcap",
8385 curproxy->nb_rsp_cap * sizeof(char *),
8386 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008387 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008388
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008389 switch (curproxy->load_server_state_from_file) {
8390 case PR_SRV_STATE_FILE_UNSPEC:
8391 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8392 break;
8393 case PR_SRV_STATE_FILE_GLOBAL:
8394 if (!global.server_state_file) {
8395 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",
8396 curproxy->id);
8397 err_code |= ERR_WARN;
8398 }
8399 break;
8400 }
8401
Willy Tarreaubaaee002006-06-26 02:48:02 +02008402 /* first, we will invert the servers list order */
8403 newsrv = NULL;
8404 while (curproxy->srv) {
8405 struct server *next;
8406
8407 next = curproxy->srv->next;
8408 curproxy->srv->next = newsrv;
8409 newsrv = curproxy->srv;
8410 if (!next)
8411 break;
8412 curproxy->srv = next;
8413 }
8414
Willy Tarreau17edc812014-01-03 12:14:34 +01008415 /* Check that no server name conflicts. This causes trouble in the stats.
8416 * We only emit a warning for the first conflict affecting each server,
8417 * in order to avoid combinatory explosion if all servers have the same
8418 * name. We do that only for servers which do not have an explicit ID,
8419 * because these IDs were made also for distinguishing them and we don't
8420 * want to annoy people who correctly manage them.
8421 */
8422 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8423 struct server *other_srv;
8424
8425 if (newsrv->puid)
8426 continue;
8427
8428 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8429 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8430 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8431 newsrv->conf.file, newsrv->conf.line,
8432 proxy_type_str(curproxy), curproxy->id,
8433 newsrv->id, other_srv->conf.line);
8434 break;
8435 }
8436 }
8437 }
8438
Willy Tarreaudd701652010-05-25 23:03:02 +02008439 /* assign automatic UIDs to servers which don't have one yet */
8440 next_id = 1;
8441 newsrv = curproxy->srv;
8442 while (newsrv != NULL) {
8443 if (!newsrv->puid) {
8444 /* server ID not set, use automatic numbering with first
8445 * spare entry starting with next_svid.
8446 */
8447 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8448 newsrv->conf.id.key = newsrv->puid = next_id;
8449 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8450 }
8451 next_id++;
8452 newsrv = newsrv->next;
8453 }
8454
Willy Tarreau20697042007-11-15 23:26:18 +01008455 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008456 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008457
Willy Tarreau62c3be22012-01-20 13:12:32 +01008458 /*
8459 * If this server supports a maxconn parameter, it needs a dedicated
8460 * tasks to fill the emptied slots when a connection leaves.
8461 * Also, resolve deferred tracking dependency if needed.
8462 */
8463 newsrv = curproxy->srv;
8464 while (newsrv != NULL) {
8465 if (newsrv->minconn > newsrv->maxconn) {
8466 /* Only 'minconn' was specified, or it was higher than or equal
8467 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8468 * this will avoid further useless expensive computations.
8469 */
8470 newsrv->maxconn = newsrv->minconn;
8471 } else if (newsrv->maxconn && !newsrv->minconn) {
8472 /* minconn was not specified, so we set it to maxconn */
8473 newsrv->minconn = newsrv->maxconn;
8474 }
8475
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008476#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008477 if (newsrv->use_ssl || newsrv->check.use_ssl)
8478 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008479#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008480
Willy Tarreau2f075e92013-12-03 11:11:34 +01008481 /* set the check type on the server */
8482 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8483
Willy Tarreau62c3be22012-01-20 13:12:32 +01008484 if (newsrv->trackit) {
8485 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008486 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008487 char *pname, *sname;
8488
8489 pname = newsrv->trackit;
8490 sname = strrchr(pname, '/');
8491
8492 if (sname)
8493 *sname++ = '\0';
8494 else {
8495 sname = pname;
8496 pname = NULL;
8497 }
8498
8499 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008500 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008501 if (!px) {
8502 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8503 proxy_type_str(curproxy), curproxy->id,
8504 newsrv->id, pname);
8505 cfgerr++;
8506 goto next_srv;
8507 }
8508 } else
8509 px = curproxy;
8510
8511 srv = findserver(px, sname);
8512 if (!srv) {
8513 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8514 proxy_type_str(curproxy), curproxy->id,
8515 newsrv->id, sname);
8516 cfgerr++;
8517 goto next_srv;
8518 }
8519
Willy Tarreau32091232014-05-16 13:52:00 +02008520 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8521 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8522 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008523 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008524 "tracking as it does not have any check nor agent enabled.\n",
8525 proxy_type_str(curproxy), curproxy->id,
8526 newsrv->id, px->id, srv->id);
8527 cfgerr++;
8528 goto next_srv;
8529 }
8530
8531 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8532
8533 if (loop) {
8534 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8535 "belongs to a tracking chain looping back to %s/%s.\n",
8536 proxy_type_str(curproxy), curproxy->id,
8537 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008538 cfgerr++;
8539 goto next_srv;
8540 }
8541
8542 if (curproxy != px &&
8543 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8544 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8545 "tracking: disable-on-404 option inconsistency.\n",
8546 proxy_type_str(curproxy), curproxy->id,
8547 newsrv->id, px->id, srv->id);
8548 cfgerr++;
8549 goto next_srv;
8550 }
8551
Willy Tarreau62c3be22012-01-20 13:12:32 +01008552 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008553 newsrv->tracknext = srv->trackers;
8554 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008555
8556 free(newsrv->trackit);
8557 newsrv->trackit = NULL;
8558 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008559
8560 /*
8561 * resolve server's resolvers name and update the resolvers pointer
8562 * accordingly
8563 */
8564 if (newsrv->resolvers_id) {
8565 struct dns_resolvers *curr_resolvers;
8566 int found;
8567
8568 found = 0;
8569 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8570 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8571 found = 1;
8572 break;
8573 }
8574 }
8575
8576 if (!found) {
8577 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8578 proxy_type_str(curproxy), curproxy->id,
8579 newsrv->id, newsrv->resolvers_id);
8580 cfgerr++;
8581 } else {
8582 free(newsrv->resolvers_id);
8583 newsrv->resolvers_id = NULL;
8584 if (newsrv->resolution)
8585 newsrv->resolution->resolvers = curr_resolvers;
8586 }
8587 }
8588 else {
8589 /* if no resolvers section associated to this server
8590 * we can clean up the associated resolution structure
8591 */
8592 if (newsrv->resolution) {
8593 free(newsrv->resolution->hostname_dn);
8594 newsrv->resolution->hostname_dn = NULL;
8595 free(newsrv->resolution);
8596 newsrv->resolution = NULL;
8597 }
8598 }
8599
Willy Tarreau62c3be22012-01-20 13:12:32 +01008600 next_srv:
8601 newsrv = newsrv->next;
8602 }
8603
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008604 /* We have to initialize the server lookup mechanism depending
8605 * on what LB algorithm was choosen.
8606 */
8607
8608 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8609 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8610 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008611 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8612 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8613 init_server_map(curproxy);
8614 } else {
8615 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8616 fwrr_init_server_groups(curproxy);
8617 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008618 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008619
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008620 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008621 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8622 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8623 fwlc_init_server_tree(curproxy);
8624 } else {
8625 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8626 fas_init_server_tree(curproxy);
8627 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008628 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008629
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008630 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008631 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8632 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8633 chash_init_server_tree(curproxy);
8634 } else {
8635 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8636 init_server_map(curproxy);
8637 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008638 break;
8639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008640
8641 if (curproxy->options & PR_O_LOGASAP)
8642 curproxy->to_log &= ~LW_BYTES;
8643
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008644 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008645 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8646 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008647 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8648 proxy_type_str(curproxy), curproxy->id);
8649 err_code |= ERR_WARN;
8650 }
8651
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008652 if (curproxy->mode != PR_MODE_HTTP) {
8653 int optnum;
8654
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008655 if (curproxy->uri_auth) {
8656 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8657 proxy_type_str(curproxy), curproxy->id);
8658 err_code |= ERR_WARN;
8659 curproxy->uri_auth = NULL;
8660 }
8661
Willy Tarreau87cf5142011-08-19 22:57:24 +02008662 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008663 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8664 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8665 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008666 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008667 }
8668
8669 if (curproxy->options & PR_O_ORGTO) {
8670 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8671 "originalto", proxy_type_str(curproxy), curproxy->id);
8672 err_code |= ERR_WARN;
8673 curproxy->options &= ~PR_O_ORGTO;
8674 }
8675
8676 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8677 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8678 (curproxy->cap & cfg_opts[optnum].cap) &&
8679 (curproxy->options & cfg_opts[optnum].val)) {
8680 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8681 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8682 err_code |= ERR_WARN;
8683 curproxy->options &= ~cfg_opts[optnum].val;
8684 }
8685 }
8686
8687 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8688 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8689 (curproxy->cap & cfg_opts2[optnum].cap) &&
8690 (curproxy->options2 & cfg_opts2[optnum].val)) {
8691 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8692 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8693 err_code |= ERR_WARN;
8694 curproxy->options2 &= ~cfg_opts2[optnum].val;
8695 }
8696 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008697
Willy Tarreau29fbe512015-08-20 19:35:14 +02008698#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008699 if (curproxy->conn_src.bind_hdr_occ) {
8700 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008701 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008702 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008703 err_code |= ERR_WARN;
8704 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008705#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008706 }
8707
Willy Tarreaubaaee002006-06-26 02:48:02 +02008708 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008709 * ensure that we're not cross-dressing a TCP server into HTTP.
8710 */
8711 newsrv = curproxy->srv;
8712 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008713 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008714 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8715 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008716 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008717 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008718
Willy Tarreau0cec3312011-10-31 13:49:26 +01008719 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8720 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8721 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8722 err_code |= ERR_WARN;
8723 }
8724
Willy Tarreauc93cd162014-05-13 15:54:22 +02008725 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008726 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8727 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8728 err_code |= ERR_WARN;
8729 }
8730
Willy Tarreau29fbe512015-08-20 19:35:14 +02008731#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008732 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8733 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008734 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 +01008735 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008736 err_code |= ERR_WARN;
8737 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008738#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008739 newsrv = newsrv->next;
8740 }
8741
Willy Tarreaue42bd962014-09-16 16:21:19 +02008742 /* check if we have a frontend with "tcp-request content" looking at L7
8743 * with no inspect-delay
8744 */
8745 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8746 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008747 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008748 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008749 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008750 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008751 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008752 break;
8753 }
8754
8755 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8756 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8757 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8758 " This means that these rules will randomly find their contents. This can be fixed by"
8759 " setting the tcp-request inspect-delay.\n",
8760 proxy_type_str(curproxy), curproxy->id);
8761 err_code |= ERR_WARN;
8762 }
8763 }
8764
Christopher Fauletd7c91962015-04-30 11:48:27 +02008765 /* Check filter configuration, if any */
8766 cfgerr += flt_check(curproxy);
8767
Willy Tarreauc1a21672009-08-16 22:37:44 +02008768 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008769 if (!curproxy->accept)
8770 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008771
Willy Tarreauc1a21672009-08-16 22:37:44 +02008772 if (curproxy->tcp_req.inspect_delay ||
8773 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008774 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008775
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008776 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008777 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008778 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008779 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008780
8781 /* both TCP and HTTP must check switching rules */
8782 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008783
8784 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008785 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008786 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8787 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008788 if (curproxy->mode == PR_MODE_HTTP) {
8789 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8790 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8791 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008792 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008793 }
8794
8795 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008796 if (curproxy->tcp_req.inspect_delay ||
8797 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8798 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8799
Emeric Brun97679e72010-09-23 17:56:44 +02008800 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8801 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8802
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008803 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008804 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008805 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008806 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008807
8808 /* If the backend does requires RDP cookie persistence, we have to
8809 * enable the corresponding analyser.
8810 */
8811 if (curproxy->options2 & PR_O2_RDPC_PRST)
8812 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008813
8814 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008815 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008816 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8817 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008818 if (curproxy->mode == PR_MODE_HTTP) {
8819 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8820 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8821 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008822 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008823 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008824 }
8825
8826 /***********************************************************/
8827 /* At this point, target names have already been resolved. */
8828 /***********************************************************/
8829
8830 /* Check multi-process mode compatibility */
8831
8832 if (global.nbproc > 1 && global.stats_fe) {
8833 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8834 unsigned long mask;
8835
8836 mask = nbits(global.nbproc);
8837 if (global.stats_fe->bind_proc)
8838 mask &= global.stats_fe->bind_proc;
8839
8840 if (bind_conf->bind_proc)
8841 mask &= bind_conf->bind_proc;
8842
8843 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008844 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008845 break;
8846 }
8847 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8848 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");
8849 }
8850 }
8851
8852 /* Make each frontend inherit bind-process from its listeners when not specified. */
8853 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8854 if (curproxy->bind_proc)
8855 continue;
8856
8857 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8858 unsigned long mask;
8859
Willy Tarreaue428b082015-05-04 21:57:58 +02008860 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008861 curproxy->bind_proc |= mask;
8862 }
8863
8864 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008865 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008866 }
8867
8868 if (global.stats_fe) {
8869 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8870 unsigned long mask;
8871
Cyril Bonté06181952016-02-24 00:14:54 +01008872 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008873 global.stats_fe->bind_proc |= mask;
8874 }
8875 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008876 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008877 }
8878
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008879 /* propagate bindings from frontends to backends. Don't do it if there
8880 * are any fatal errors as we must not call it with unresolved proxies.
8881 */
8882 if (!cfgerr) {
8883 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8884 if (curproxy->cap & PR_CAP_FE)
8885 propagate_processes(curproxy, NULL);
8886 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008887 }
8888
8889 /* Bind each unbound backend to all processes when not specified. */
8890 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8891 if (curproxy->bind_proc)
8892 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008893 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008894 }
8895
8896 /*******************************************************/
8897 /* At this step, all proxies have a non-null bind_proc */
8898 /*******************************************************/
8899
8900 /* perform the final checks before creating tasks */
8901
8902 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8903 struct listener *listener;
8904 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008905
Emeric Brunc52962f2012-11-15 18:28:02 +01008906#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008907 /* Configure SSL for each bind line.
8908 * Note: if configuration fails at some point, the ->ctx member
8909 * remains NULL so that listeners can later detach.
8910 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008911 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008912 int alloc_ctx;
8913
Emeric Brunc52962f2012-11-15 18:28:02 +01008914 if (!bind_conf->is_ssl) {
8915 if (bind_conf->default_ctx) {
8916 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8917 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8918 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008919 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008920 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008921 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008922 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008923 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008924 cfgerr++;
8925 continue;
8926 }
8927
Emeric Brun8dc60392014-05-09 13:52:00 +02008928 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008929 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008930 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8931 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");
8932 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008933 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008934 cfgerr++;
8935 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008936 }
8937
Emeric Brunfc0421f2012-09-07 17:30:07 +02008938 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008939 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008940
8941 /* initialize CA variables if the certificates generation is enabled */
8942 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008943 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008944#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008945
Willy Tarreaue6b98942007-10-29 01:09:36 +01008946 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008947 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008948 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008949 int nbproc;
8950
8951 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008952 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008953 nbits(global.nbproc));
8954
8955 if (!nbproc) /* no intersection between listener and frontend */
8956 nbproc = 1;
8957
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008958 if (!listener->luid) {
8959 /* listener ID not set, use automatic numbering with first
8960 * spare entry starting with next_luid.
8961 */
8962 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8963 listener->conf.id.key = listener->luid = next_id;
8964 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008965 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008966 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008967
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008968 /* enable separate counters */
8969 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008970 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008971 if (!listener->name)
8972 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008973 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008974
Willy Tarreaue6b98942007-10-29 01:09:36 +01008975 if (curproxy->options & PR_O_TCP_NOLING)
8976 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008977 if (!listener->maxconn)
8978 listener->maxconn = curproxy->maxconn;
8979 if (!listener->backlog)
8980 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008981 if (!listener->maxaccept)
8982 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8983
8984 /* we want to have an optimal behaviour on single process mode to
8985 * maximize the work at once, but in multi-process we want to keep
8986 * some fairness between processes, so we target half of the max
8987 * number of events to be balanced over all the processes the proxy
8988 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8989 * used to disable the limit.
8990 */
8991 if (listener->maxaccept > 0) {
8992 if (nbproc > 1)
8993 listener->maxaccept = (listener->maxaccept + 1) / 2;
8994 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8995 }
8996
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008997 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008998 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008999 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009000 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009001
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009002 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009003 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009004
Willy Tarreau620408f2016-10-21 16:37:51 +02009005 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9006 listener->options |= LI_O_TCP_L5_RULES;
9007
Willy Tarreaude3041d2010-05-31 10:56:17 +02009008 if (curproxy->mon_mask.s_addr)
9009 listener->options |= LI_O_CHK_MONNET;
9010
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009011 /* smart accept mode is automatic in HTTP mode */
9012 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009013 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009014 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9015 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009016 }
9017
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009018 /* Release unused SSL configs */
9019 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
9020 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009021 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009022#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02009023 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009024 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009025 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02009026 free(bind_conf->ca_sign_file);
9027 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009028 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009029 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009030 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009031 if(bind_conf->keys_ref) {
9032 free(bind_conf->keys_ref->filename);
9033 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009034 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009035 free(bind_conf->keys_ref);
9036 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009037#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009038 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009039
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009040 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009041 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009042 int count, maxproc = 0;
9043
9044 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009045 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009046 if (count > maxproc)
9047 maxproc = count;
9048 }
9049 /* backends have 0, frontends have 1 or more */
9050 if (maxproc != 1)
9051 Warning("Proxy '%s': in multi-process mode, stats will be"
9052 " limited to process assigned to the current request.\n",
9053 curproxy->id);
9054
Willy Tarreau102df612014-05-07 23:56:38 +02009055 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9056 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9057 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009058 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009059 }
Willy Tarreau102df612014-05-07 23:56:38 +02009060 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9061 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9062 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009063 }
9064 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009065
9066 /* create the task associated with the proxy */
9067 curproxy->task = task_new();
9068 if (curproxy->task) {
9069 curproxy->task->context = curproxy;
9070 curproxy->task->process = manage_proxy;
9071 /* no need to queue, it will be done automatically if some
9072 * listener gets limited.
9073 */
9074 curproxy->task->expire = TICK_ETERNITY;
9075 } else {
9076 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9077 curproxy->id);
9078 cfgerr++;
9079 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009080 }
9081
Willy Tarreaufbb78422011-06-05 15:38:35 +02009082 /* automatically compute fullconn if not set. We must not do it in the
9083 * loop above because cross-references are not yet fully resolved.
9084 */
9085 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9086 /* If <fullconn> is not set, let's set it to 10% of the sum of
9087 * the possible incoming frontend's maxconns.
9088 */
9089 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9090 struct proxy *fe;
9091 int total = 0;
9092
9093 /* sum up the number of maxconns of frontends which
9094 * reference this backend at least once or which are
9095 * the same one ('listen').
9096 */
9097 for (fe = proxy; fe; fe = fe->next) {
9098 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009099 int found = 0;
9100
9101 if (!(fe->cap & PR_CAP_FE))
9102 continue;
9103
9104 if (fe == curproxy) /* we're on a "listen" instance */
9105 found = 1;
9106
9107 if (fe->defbe.be == curproxy) /* "default_backend" */
9108 found = 1;
9109
9110 /* check if a "use_backend" rule matches */
9111 if (!found) {
9112 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009113 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009114 found = 1;
9115 break;
9116 }
9117 }
9118 }
9119
Willy Tarreaufbb78422011-06-05 15:38:35 +02009120 /* now we've checked all possible ways to reference a backend
9121 * from a frontend.
9122 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009123 if (!found)
9124 continue;
9125 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009126 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009127 /* we have the sum of the maxconns in <total>. We only
9128 * keep 10% of that sum to set the default fullconn, with
9129 * a hard minimum of 1 (to avoid a divide by zero).
9130 */
9131 curproxy->fullconn = (total + 9) / 10;
9132 if (!curproxy->fullconn)
9133 curproxy->fullconn = 1;
9134 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009135 }
9136
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009137 /*
9138 * Recount currently required checks.
9139 */
9140
9141 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9142 int optnum;
9143
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009144 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9145 if (curproxy->options & cfg_opts[optnum].val)
9146 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009147
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009148 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9149 if (curproxy->options2 & cfg_opts2[optnum].val)
9150 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009151 }
9152
Willy Tarreau0fca4832015-05-01 19:12:05 +02009153 /* compute the required process bindings for the peers */
9154 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9155 if (curproxy->table.peers.p)
9156 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9157
Willy Tarreau122541c2011-09-07 21:24:49 +02009158 if (peers) {
9159 struct peers *curpeers = peers, **last;
9160 struct peer *p, *pb;
9161
Willy Tarreau1e273012015-05-01 19:15:17 +02009162 /* Remove all peers sections which don't have a valid listener,
9163 * which are not used by any table, or which are bound to more
9164 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009165 */
9166 last = &peers;
9167 while (*last) {
9168 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009169
9170 if (curpeers->state == PR_STSTOPPED) {
9171 /* the "disabled" keyword was present */
9172 if (curpeers->peers_fe)
9173 stop_proxy(curpeers->peers_fe);
9174 curpeers->peers_fe = NULL;
9175 }
9176 else if (!curpeers->peers_fe) {
9177 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9178 curpeers->id, localpeer);
9179 }
David Carliere6c39412015-07-02 07:00:17 +00009180 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009181 /* either it's totally stopped or too much used */
9182 if (curpeers->peers_fe->bind_proc) {
9183 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009184 "running in different processes (%d different ones). "
9185 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009186 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009187 cfgerr++;
9188 }
9189 stop_proxy(curpeers->peers_fe);
9190 curpeers->peers_fe = NULL;
9191 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009192 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009193 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009194 last = &curpeers->next;
9195 continue;
9196 }
9197
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009198 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009199 p = curpeers->remote;
9200 while (p) {
9201 pb = p->next;
9202 free(p->id);
9203 free(p);
9204 p = pb;
9205 }
9206
9207 /* Destroy and unlink this curpeers section.
9208 * Note: curpeers is backed up into *last.
9209 */
9210 free(curpeers->id);
9211 curpeers = curpeers->next;
9212 free(*last);
9213 *last = curpeers;
9214 }
9215 }
9216
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009217 /* initialize stick-tables on backend capable proxies. This must not
9218 * be done earlier because the data size may be discovered while parsing
9219 * other proxies.
9220 */
9221 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9222 if (curproxy->state == PR_STSTOPPED)
9223 continue;
9224
9225 if (!stktable_init(&curproxy->table)) {
9226 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9227 cfgerr++;
9228 }
9229 }
9230
Simon Horman0d16a402015-01-30 11:22:58 +09009231 if (mailers) {
9232 struct mailers *curmailers = mailers, **last;
9233 struct mailer *m, *mb;
9234
9235 /* Remove all mailers sections which don't have a valid listener.
9236 * This can happen when a mailers section is never referenced.
9237 */
9238 last = &mailers;
9239 while (*last) {
9240 curmailers = *last;
9241 if (curmailers->users) {
9242 last = &curmailers->next;
9243 continue;
9244 }
9245
9246 Warning("Removing incomplete section 'mailers %s'.\n",
9247 curmailers->id);
9248
9249 m = curmailers->mailer_list;
9250 while (m) {
9251 mb = m->next;
9252 free(m->id);
9253 free(m);
9254 m = mb;
9255 }
9256
9257 /* Destroy and unlink this curmailers section.
9258 * Note: curmailers is backed up into *last.
9259 */
9260 free(curmailers->id);
9261 curmailers = curmailers->next;
9262 free(*last);
9263 *last = curmailers;
9264 }
9265 }
9266
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009267 /* Update server_state_file_name to backend name if backend is supposed to use
9268 * a server-state file locally defined and none has been provided */
9269 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9270 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9271 curproxy->server_state_file_name == NULL)
9272 curproxy->server_state_file_name = strdup(curproxy->id);
9273 }
9274
Willy Tarreau34eb6712011-10-24 18:15:04 +02009275 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009276 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009277 MEM_F_SHARED);
9278
Willy Tarreaubb925012009-07-23 13:36:36 +02009279 if (cfgerr > 0)
9280 err_code |= ERR_ALERT | ERR_FATAL;
9281 out:
9282 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009283}
9284
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009285/*
9286 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9287 * parsing sessions.
9288 */
9289void cfg_register_keywords(struct cfg_kw_list *kwl)
9290{
9291 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9292}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009293
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009294/*
9295 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9296 */
9297void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9298{
9299 LIST_DEL(&kwl->list);
9300 LIST_INIT(&kwl->list);
9301}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009302
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009303/* this function register new section in the haproxy configuration file.
9304 * <section_name> is the name of this new section and <section_parser>
9305 * is the called parser. If two section declaration have the same name,
9306 * only the first declared is used.
9307 */
9308int cfg_register_section(char *section_name,
9309 int (*section_parser)(const char *, int, char **, int))
9310{
9311 struct cfg_section *cs;
9312
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009313 list_for_each_entry(cs, &sections, list) {
9314 if (strcmp(cs->section_name, section_name) == 0) {
9315 Alert("register section '%s': already registered.\n", section_name);
9316 return 0;
9317 }
9318 }
9319
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009320 cs = calloc(1, sizeof(*cs));
9321 if (!cs) {
9322 Alert("register section '%s': out of memory.\n", section_name);
9323 return 0;
9324 }
9325
9326 cs->section_name = section_name;
9327 cs->section_parser = section_parser;
9328
9329 LIST_ADDQ(&sections, &cs->list);
9330
9331 return 1;
9332}
9333
Willy Tarreaubaaee002006-06-26 02:48:02 +02009334/*
David Carlier845efb52015-09-25 11:49:18 +01009335 * free all config section entries
9336 */
9337void cfg_unregister_sections(void)
9338{
9339 struct cfg_section *cs, *ics;
9340
9341 list_for_each_entry_safe(cs, ics, &sections, list) {
9342 LIST_DEL(&cs->list);
9343 free(cs);
9344 }
9345}
9346
Christopher Faulet7110b402016-10-26 11:09:44 +02009347void cfg_backup_sections(struct list *backup_sections)
9348{
9349 struct cfg_section *cs, *ics;
9350
9351 list_for_each_entry_safe(cs, ics, &sections, list) {
9352 LIST_DEL(&cs->list);
9353 LIST_ADDQ(backup_sections, &cs->list);
9354 }
9355}
9356
9357void cfg_restore_sections(struct list *backup_sections)
9358{
9359 struct cfg_section *cs, *ics;
9360
9361 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9362 LIST_DEL(&cs->list);
9363 LIST_ADDQ(&sections, &cs->list);
9364 }
9365}
9366
Willy Tarreau659fbf02016-05-26 17:55:28 +02009367__attribute__((constructor))
9368static void cfgparse_init(void)
9369{
9370 /* Register internal sections */
9371 cfg_register_section("listen", cfg_parse_listen);
9372 cfg_register_section("frontend", cfg_parse_listen);
9373 cfg_register_section("backend", cfg_parse_listen);
9374 cfg_register_section("defaults", cfg_parse_listen);
9375 cfg_register_section("global", cfg_parse_global);
9376 cfg_register_section("userlist", cfg_parse_users);
9377 cfg_register_section("peers", cfg_parse_peers);
9378 cfg_register_section("mailers", cfg_parse_mailers);
9379 cfg_register_section("namespace_list", cfg_parse_netns);
9380 cfg_register_section("resolvers", cfg_parse_resolvers);
9381}
9382
David Carlier845efb52015-09-25 11:49:18 +01009383/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009384 * Local variables:
9385 * c-indent-level: 8
9386 * c-basic-offset: 8
9387 * End:
9388 */