blob: cc2f507e7d779d58b30ed528f8a7dbbb1072360a [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
Willy Tarreaueb0c6142007-05-07 00:53:22 +020055#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010056#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020058#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020060#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020061#include <proto/dumpstats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020062#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020063#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020064#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020065#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010066#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020067#include <proto/lb_fwlc.h>
68#include <proto/lb_fwrr.h>
69#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020074#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020082#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Emeric Brunfc0421f2012-09-07 17:30:07 +020086#ifdef USE_OPENSSL
87#include <types/ssl_sock.h>
88#include <proto/ssl_sock.h>
89#include <proto/shctx.h>
90#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020091
Willy Tarreauf3c69202006-07-09 16:42:34 +020092/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
93 * ssl-hello-chk option to ensure that the remote server speaks SSL.
94 *
95 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
96 */
97const char sslv3_client_hello_pkt[] = {
98 "\x16" /* ContentType : 0x16 = Hanshake */
99 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
100 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
101 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
102 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
103 "\x03\x00" /* Hello Version : 0x0300 = v3 */
104 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
105 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
106 "\x00" /* Session ID length : empty (no session ID) */
107 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
108 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
109 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
110 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
111 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
112 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
113 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
114 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
115 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
116 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
117 "\x00\x38" "\x00\x39" "\x00\x3A"
118 "\x01" /* Compression Length : 0x01 = 1 byte for types */
119 "\x00" /* Compression Type : 0x00 = NULL compression */
120};
121
Willy Tarreau3842f002009-06-14 11:39:52 +0200122/* various keyword modifiers */
123enum kw_mod {
124 KWM_STD = 0, /* normal */
125 KWM_NO, /* "no" prefixed before the keyword */
126 KWM_DEF, /* "default" prefixed before the keyword */
127};
128
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100129/* permit to store configuration section */
130struct cfg_section {
131 struct list list;
132 char *section_name;
133 int (*section_parser)(const char *, int, char **, int);
134};
135
136/* Used to chain configuration sections definitions. This list
137 * stores struct cfg_section
138 */
139struct list sections = LIST_HEAD_INIT(sections);
140
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143 const char *name;
144 unsigned int val;
145 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100146 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148};
149
150/* proxy->options */
151static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100152{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
154 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
155 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
157 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
158 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200160 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200161 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100162 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
164 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
165 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100167#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100169#else
170 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100171#endif
172
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100174};
175
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176/* proxy->options2 */
177static const struct cfg_opt cfg_opts2[] =
178{
179#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
181 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100183#else
184 { "splice-request", 0, 0, 0, 0 },
185 { "splice-response", 0, 0, 0, 0 },
186 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
189 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
190 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
191 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
192 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
193 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
194 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
196 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400197 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100198 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200199 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200200 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100201 { NULL, 0, 0, 0 }
202};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau6daf3432008-01-22 16:44:08 +0100204static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
206int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100207int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200209/* List head of all known configuration keywords */
210static struct cfg_kw_list cfg_keywords = {
211 .list = LIST_HEAD_INIT(cfg_keywords.list)
212};
213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214/*
215 * converts <str> to a list of listeners which are dynamically allocated.
216 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
217 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
218 * - <port> is a numerical port from 1 to 65535 ;
219 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
220 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
222 * not NULL, it must be a valid pointer to either NULL or a freeable area that
223 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226{
227 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 int port, end;
230
231 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100234 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100235 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237 str = next;
238 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100239 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 *next++ = 0;
241 }
242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200244 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200245 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (!ss2)
247 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200251 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100255 if (!port || !end) {
256 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
257 goto fail;
258 }
259
Emeric Bruned760922010-10-22 17:59:25 +0200260 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
264
265 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200266 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200267 goto fail;
268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100270 else if (ss2->ss_family == AF_UNSPEC) {
271 socklen_t addr_len;
272
273 /* We want to attach to an already bound fd whose number
274 * is in the addr part of ss2 when cast to sockaddr_in.
275 * Note that by definition there is a single listener.
276 * We still have to determine the address family to
277 * register the correct protocol.
278 */
279 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
280 addr_len = sizeof(*ss2);
281 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
282 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
283 goto fail;
284 }
285
286 port = end = get_host_port(ss2);
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200290 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200293 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100294 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
296 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
297 l->frontend = curproxy;
298 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299
Willy Tarreau40aa0702013-03-10 23:51:38 +0100300 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200301 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau620408f2016-10-21 16:37:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request session' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200374/* Report a warning if a rule is placed after a 'tcp-request content' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
377int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
378{
379 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau61d18892009-03-31 10:49:21 +0200387/* Report a warning if a rule is placed after a 'block' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200392 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200393 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau5002f572014-04-23 01:32:02 +0200400/* Report a warning if a rule is placed after an 'http_request' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
403int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
404{
405 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreau61d18892009-03-31 10:49:21 +0200413/* Report a warning if a rule is placed after a reqrewrite rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
418 if (proxy->req_exp) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a reqadd rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100431 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a redirect rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
452/* Report a warning if a rule is placed after a 'use_backend' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100455int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200456{
457 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreauee445d92014-04-23 01:39:04 +0200465/* Report a warning if a rule is placed after a 'use-server' rule.
466 * Return 1 if the warning has been emitted, otherwise 0.
467 */
468int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
469{
470 if (!LIST_ISEMPTY(&proxy->server_rules)) {
471 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
472 file, line, arg);
473 return 1;
474 }
475 return 0;
476}
477
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200478/* report a warning if a "tcp request connection" rule is dangerously placed */
479int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
480{
Willy Tarreau620408f2016-10-21 16:37:51 +0200481 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
482 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
483 warnif_rule_after_block(proxy, file, line, arg) ||
484 warnif_rule_after_http_req(proxy, file, line, arg) ||
485 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
486 warnif_rule_after_reqadd(proxy, file, line, arg) ||
487 warnif_rule_after_redirect(proxy, file, line, arg) ||
488 warnif_rule_after_use_backend(proxy, file, line, arg) ||
489 warnif_rule_after_use_server(proxy, file, line, arg);
490}
491
492int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
493{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200494 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
495 warnif_rule_after_block(proxy, file, line, arg) ||
496 warnif_rule_after_http_req(proxy, file, line, arg) ||
497 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
498 warnif_rule_after_reqadd(proxy, file, line, arg) ||
499 warnif_rule_after_redirect(proxy, file, line, arg) ||
500 warnif_rule_after_use_backend(proxy, file, line, arg) ||
501 warnif_rule_after_use_server(proxy, file, line, arg);
502}
503
504/* report a warning if a "tcp request content" rule is dangerously placed */
505int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
506{
507 return warnif_rule_after_block(proxy, file, line, arg) ||
508 warnif_rule_after_http_req(proxy, file, line, arg) ||
509 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
510 warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
514}
515
Willy Tarreau61d18892009-03-31 10:49:21 +0200516/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
Willy Tarreau5002f572014-04-23 01:32:02 +0200519 return warnif_rule_after_http_req(proxy, file, line, arg) ||
520 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
521 warnif_rule_after_reqadd(proxy, file, line, arg) ||
522 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200523 warnif_rule_after_use_backend(proxy, file, line, arg) ||
524 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200525}
526
527/* report a warning if an http-request rule is dangerously placed */
528int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
529{
Willy Tarreau61d18892009-03-31 10:49:21 +0200530 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
531 warnif_rule_after_reqadd(proxy, file, line, arg) ||
532 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200533 warnif_rule_after_use_backend(proxy, file, line, arg) ||
534 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200535}
536
537/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100538int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200539{
540 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
541 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200542 warnif_rule_after_use_backend(proxy, file, line, arg) ||
543 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
546/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100547int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
549 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200550 warnif_rule_after_use_backend(proxy, file, line, arg) ||
551 warnif_rule_after_use_server(proxy, file, line, arg);
552}
553
554/* report a warning if a redirect rule is dangerously placed */
555int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
556{
557 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
558 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200559}
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561/* Report it if a request ACL condition uses some keywords that are incompatible
562 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
563 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
564 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200569 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100570
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100571 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 return 0;
573
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 acl = acl_cond_conflicts(cond, where);
575 if (acl) {
576 if (acl->name && *acl->name)
577 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
578 file, line, acl->name, sample_ckp_names(where));
579 else
580 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200581 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 return ERR_WARN;
583 }
584 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100585 return 0;
586
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100587 if (acl->name && *acl->name)
588 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200589 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100590 else
591 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200592 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100593 return ERR_WARN;
594}
595
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 * parse a line in a <global> section. Returns the error code, 0 if OK, or
598 * any combination of :
599 * - ERR_ABORT: must abort ASAP
600 * - ERR_FATAL: we can continue parsing but not start the service
601 * - ERR_WARN: a warning has been emitted
602 * - ERR_ALERT: an alert has been emitted
603 * Only the two first ones can stop processing, the two others are just
604 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200606int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607{
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200609 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610
611 if (!strcmp(args[0], "global")) { /* new section */
612 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200613 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200616 else if (!strcmp(args[0], "ca-base")) {
617#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200618 if(alertif_too_many_args(1, file, linenum, args, &err_code))
619 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200620 if (global.ca_base != NULL) {
621 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT;
623 goto out;
624 }
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630 global.ca_base = strdup(args[1]);
631#else
632 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635#endif
636 }
637 else if (!strcmp(args[0], "crt-base")) {
638#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
640 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200641 if (global.crt_base != NULL) {
642 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT;
644 goto out;
645 }
646 if (*(args[1]) == 0) {
647 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
648 err_code |= ERR_ALERT | ERR_FATAL;
649 goto out;
650 }
651 global.crt_base = strdup(args[1]);
652#else
653 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656#endif
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 global.mode |= MODE_DAEMON;
662 }
663 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_DEBUG;
667 }
668 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(0, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100671 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200673 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200674 if (alertif_too_many_args(0, file, linenum, args, &err_code))
675 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100676 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200679 if (alertif_too_many_args(0, file, linenum, args, &err_code))
680 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100681 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100683 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(0, file, linenum, args, &err_code))
685 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100686 global.tune.options &= ~GTUNE_USE_SPLICE;
687 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200688 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200689 if (alertif_too_many_args(0, file, linenum, args, &err_code))
690 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200691 global.tune.options &= ~GTUNE_USE_GAI;
692 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000693 else if (!strcmp(args[0], "noreuseport")) {
694 if (alertif_too_many_args(0, file, linenum, args, &err_code))
695 goto out;
696 global.tune.options &= ~GTUNE_USE_REUSEPORT;
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(0, file, linenum, args, &err_code))
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 global.mode |= MODE_QUIET;
702 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200703 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
705 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200706 if (global.tune.maxpollevents != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT;
709 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200715 }
716 global.tune.maxpollevents = atol(args[1]);
717 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100718 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
720 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100721 if (global.tune.maxaccept != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT;
724 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100730 }
731 global.tune.maxaccept = atol(args[1]);
732 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200733 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.chksize = atol(args[1]);
742 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100743 else if (!strcmp(args[0], "tune.recv_enough")) {
744 if (alertif_too_many_args(1, file, linenum, args, &err_code))
745 goto out;
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.tune.recv_enough = atol(args[1]);
752 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200753#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200754 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200755 if (alertif_too_many_args(0, file, linenum, args, &err_code))
756 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200757 global.tune.sslprivatecache = 1;
758 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100759 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.sslcachesize = atol(args[1]);
768 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100769 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
770 unsigned int ssllifetime;
771 const char *res;
772
William Lallemand1a748ae2015-05-19 16:37:23 +0200773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
774 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780
781 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
782 if (res) {
783 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
784 file, linenum, *res, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788
789 global.tune.ssllifetime = ssllifetime;
790 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100791 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200792 if (alertif_too_many_args(1, file, linenum, args, &err_code))
793 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.ssl_max_record = atol(args[1]);
800 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200801#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200802 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.ssl_default_dh_param = atol(args[1]);
811 if (global.tune.ssl_default_dh_param < 1024) {
812 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200817#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200818 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.ssl_ctx_cache = atoi(args[1]);
827 if (global.tune.ssl_ctx_cache < 0) {
828 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200834#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100835 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.buf_limit = atol(args[1]);
844 if (global.tune.buf_limit) {
845 if (global.tune.buf_limit < 3)
846 global.tune.buf_limit = 3;
847 if (global.tune.buf_limit <= global.tune.reserved_bufs)
848 global.tune.buf_limit = global.tune.reserved_bufs + 1;
849 }
850 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100851 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.reserved_bufs = atol(args[1]);
860 if (global.tune.reserved_bufs < 2)
861 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100862 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
863 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200866 if (alertif_too_many_args(1, file, linenum, args, &err_code))
867 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200868 if (*(args[1]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200874 if (global.tune.bufsize <= 0) {
875 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100879 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100880 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200881 }
882 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200891 if (global.tune.maxrewrite < 0) {
892 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200896 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100897 else if (!strcmp(args[0], "tune.idletimer")) {
898 unsigned int idle;
899 const char *res;
900
William Lallemand1a748ae2015-05-19 16:37:23 +0200901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908
909 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
910 if (res) {
911 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
912 file, linenum, *res, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916
917 if (idle > 65535) {
918 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 global.tune.idle_timer = idle;
923 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100924 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200925 if (alertif_too_many_args(1, file, linenum, args, &err_code))
926 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100927 if (global.tune.client_rcvbuf != 0) {
928 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
929 err_code |= ERR_ALERT;
930 goto out;
931 }
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 global.tune.client_rcvbuf = atol(args[1]);
938 }
939 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200940 if (alertif_too_many_args(1, file, linenum, args, &err_code))
941 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100942 if (global.tune.server_rcvbuf != 0) {
943 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
944 err_code |= ERR_ALERT;
945 goto out;
946 }
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 global.tune.server_rcvbuf = atol(args[1]);
953 }
954 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100957 if (global.tune.client_sndbuf != 0) {
958 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT;
960 goto out;
961 }
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 global.tune.client_sndbuf = atol(args[1]);
968 }
969 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(1, file, linenum, args, &err_code))
971 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100972 if (global.tune.server_sndbuf != 0) {
973 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT;
975 goto out;
976 }
977 if (*(args[1]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982 global.tune.server_sndbuf = atol(args[1]);
983 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200984 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992 global.tune.pipesize = atol(args[1]);
993 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100994 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200995 if (alertif_too_many_args(1, file, linenum, args, &err_code))
996 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 global.tune.cookie_len = atol(args[1]) + 1;
1003 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001004 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001005 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1006 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.tune.max_http_hdr = atol(args[1]);
1013 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001014 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1015#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001016 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1017 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001018 if (*args[1]) {
1019 global.tune.zlibmemlevel = atoi(args[1]);
1020 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1021 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 } else {
1027 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
1038 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1039#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1041 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001042 if (*args[1]) {
1043 global.tune.zlibwindowsize = atoi(args[1]);
1044 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1045 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 } else {
1051 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1052 file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056#else
1057 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060#endif
1061 }
William Lallemandf3747832012-11-09 12:33:10 +01001062 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001063 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1064 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001065 if (*args[1]) {
1066 global.tune.comp_maxlevel = atoi(args[1]);
1067 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1068 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1069 file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 } else {
1074 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1075 file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001080 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1081 if (*args[1]) {
1082 global.tune.pattern_cache = atoi(args[1]);
1083 if (global.tune.pattern_cache < 0) {
1084 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1085 file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 } else {
1090 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1091 file, linenum, args[0]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001097 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001101 err_code |= ERR_ALERT;
1102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001109 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1110 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
1111 err_code |= ERR_WARN;
1112 goto out;
1113 }
1114
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 }
1116 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001120 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT;
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001129 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1130 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
1131 err_code |= ERR_WARN;
1132 goto out;
1133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 }
Simon Horman98637e52014-06-20 12:30:16 +09001135 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001136 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1137 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001138 global.external_check = 1;
1139 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001140 /* user/group name handling */
1141 else if (!strcmp(args[0], "user")) {
1142 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1144 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001145 if (global.uid != 0) {
1146 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001149 }
1150 errno = 0;
1151 ha_user = getpwnam(args[1]);
1152 if (ha_user != NULL) {
1153 global.uid = (int)ha_user->pw_uid;
1154 }
1155 else {
1156 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001158 }
1159 }
1160 else if (!strcmp(args[0], "group")) {
1161 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001164 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001165 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001168 }
1169 errno = 0;
1170 ha_group = getgrnam(args[1]);
1171 if (ha_group != NULL) {
1172 global.gid = (int)ha_group->gr_gid;
1173 }
1174 else {
1175 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001177 }
1178 }
1179 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001181 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 if (*(args[1]) == 0) {
1184 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
1188 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001189 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1190 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1191 file, linenum, args[0], LONGBITS, global.nbproc);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
1196 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001197 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 if (global.maxconn != 0) {
1200 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 global.maxconn = atol(args[1]);
1210#ifdef SYSTEM_MAXCONN
1211 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1212 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1213 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001214 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 }
1216#endif /* SYSTEM_MAXCONN */
1217 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001218 else if (!strcmp(args[0], "maxsslconn")) {
1219#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001220 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1221 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001222 if (*(args[1]) == 0) {
1223 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 global.maxsslconn = atol(args[1]);
1228#else
Emeric Brun0914df82012-10-02 18:45:42 +02001229 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001232#endif
1233 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001234 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1235#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001236 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1237 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243 free(global.listen_default_ciphers);
1244 global.listen_default_ciphers = strdup(args[1]);
1245#else
1246 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249#endif
1250 }
1251 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1252#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001253 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1254 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001255 if (*(args[1]) == 0) {
1256 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260 free(global.connect_default_ciphers);
1261 global.connect_default_ciphers = strdup(args[1]);
1262#else
1263 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266#endif
1267 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001268#ifdef USE_OPENSSL
1269#ifndef OPENSSL_NO_DH
1270 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1271 if (*(args[1]) == 0) {
1272 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1277 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281 }
1282#endif
1283#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001284 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001285 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1286 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001287 if (*(args[1]) == 0) {
1288 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto out;
1291 }
1292 if (strcmp(args[1],"none") == 0)
1293 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1294 else if (strcmp(args[1],"required") == 0)
1295 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1296 else {
1297 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001302 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001303 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1304 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001305 if (global.cps_lim != 0) {
1306 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1307 err_code |= ERR_ALERT;
1308 goto out;
1309 }
1310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.cps_lim = atol(args[1]);
1316 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001317 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001320 if (global.sps_lim != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1322 err_code |= ERR_ALERT;
1323 goto out;
1324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 global.sps_lim = atol(args[1]);
1331 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001332 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001335 if (global.ssl_lim != 0) {
1336 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT;
1338 goto out;
1339 }
1340 if (*(args[1]) == 0) {
1341 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 global.ssl_lim = atol(args[1]);
1346 }
William Lallemandd85f9172012-11-09 17:05:39 +01001347 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001348 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1349 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001350 if (*(args[1]) == 0) {
1351 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 global.comp_rate_lim = atoi(args[1]) * 1024;
1356 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001357 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001358 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1359 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001360 if (global.maxpipes != 0) {
1361 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001362 err_code |= ERR_ALERT;
1363 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001364 }
1365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001369 }
1370 global.maxpipes = atol(args[1]);
1371 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001372 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001373 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1374 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
William Lallemande3a7d992012-11-20 11:25:20 +01001380 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001381 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001382 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001385 if (*(args[1]) == 0) {
1386 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001391 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001392 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001396 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 if (global.rlimit_nofile != 0) {
1402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001403 err_code |= ERR_ALERT;
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
1406 if (*(args[1]) == 0) {
1407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
1409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
1411 global.rlimit_nofile = atol(args[1]);
1412 }
1413 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001414 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 if (global.chroot != NULL) {
1417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001418 err_code |= ERR_ALERT;
1419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 }
1421 if (*(args[1]) == 0) {
1422 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001423 err_code |= ERR_ALERT | ERR_FATAL;
1424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 }
1426 global.chroot = strdup(args[1]);
1427 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001428 else if (!strcmp(args[0], "description")) {
1429 int i, len=0;
1430 char *d;
1431
1432 if (!*args[1]) {
1433 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1434 file, linenum, args[0]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
1437 }
1438
Willy Tarreau348acfe2014-04-14 15:00:39 +02001439 for (i = 1; *args[i]; i++)
1440 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001441
1442 if (global.desc)
1443 free(global.desc);
1444
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001445 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001446
Willy Tarreau348acfe2014-04-14 15:00:39 +02001447 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1448 for (i = 2; *args[i]; i++)
1449 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001450 }
1451 else if (!strcmp(args[0], "node")) {
1452 int i;
1453 char c;
1454
William Lallemand1a748ae2015-05-19 16:37:23 +02001455 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1456 goto out;
1457
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001458 for (i=0; args[1][i]; i++) {
1459 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001460 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1461 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001462 break;
1463 }
1464
1465 if (!i || args[1][i]) {
1466 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1467 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1468 file, linenum, args[0]);
1469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
1471 }
1472
1473 if (global.node)
1474 free(global.node);
1475
1476 global.node = strdup(args[1]);
1477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001479 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 if (global.pidfile != NULL) {
1482 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
1486 if (*(args[1]) == 0) {
1487 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 }
1491 global.pidfile = strdup(args[1]);
1492 }
Emeric Bruned760922010-10-22 17:59:25 +02001493 else if (!strcmp(args[0], "unix-bind")) {
1494 int cur_arg = 1;
1495 while (*(args[cur_arg])) {
1496 if (!strcmp(args[cur_arg], "prefix")) {
1497 if (global.unix_bind.prefix != NULL) {
1498 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1499 err_code |= ERR_ALERT;
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (*(args[cur_arg+1]) == 0) {
1505 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1510 cur_arg += 2;
1511 continue;
1512 }
1513
1514 if (!strcmp(args[cur_arg], "mode")) {
1515
1516 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1517 cur_arg += 2;
1518 continue;
1519 }
1520
1521 if (!strcmp(args[cur_arg], "uid")) {
1522
1523 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1524 cur_arg += 2;
1525 continue;
1526 }
1527
1528 if (!strcmp(args[cur_arg], "gid")) {
1529
1530 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1531 cur_arg += 2;
1532 continue;
1533 }
1534
1535 if (!strcmp(args[cur_arg], "user")) {
1536 struct passwd *user;
1537
1538 user = getpwnam(args[cur_arg + 1]);
1539 if (!user) {
1540 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1541 file, linenum, args[0], args[cur_arg + 1 ]);
1542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
1544 }
1545
1546 global.unix_bind.ux.uid = user->pw_uid;
1547 cur_arg += 2;
1548 continue;
1549 }
1550
1551 if (!strcmp(args[cur_arg], "group")) {
1552 struct group *group;
1553
1554 group = getgrnam(args[cur_arg + 1]);
1555 if (!group) {
1556 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1557 file, linenum, args[0], args[cur_arg + 1 ]);
1558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
1560 }
1561
1562 global.unix_bind.ux.gid = group->gr_gid;
1563 cur_arg += 2;
1564 continue;
1565 }
1566
Willy Tarreaub48f9582011-09-05 01:17:06 +02001567 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001568 file, linenum, args[0]);
1569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
1571 }
1572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1574 /* delete previous herited or defined syslog servers */
1575 struct logsrv *back;
1576 struct logsrv *tmp;
1577
1578 if (*(args[1]) != 0) {
1579 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
1583
1584 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1585 LIST_DEL(&tmp->list);
1586 free(tmp);
1587 }
1588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001590 struct sockaddr_storage *sk;
1591 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001592 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001593 int arg = 0;
1594 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001595
William Lallemand1a748ae2015-05-19 16:37:23 +02001596 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1597 goto out;
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 if (*(args[1]) == 0 || *(args[2]) == 0) {
1600 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001601 err_code |= ERR_ALERT | ERR_FATAL;
1602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
William Lallemand0f99e342011-10-12 17:50:54 +02001604
Vincent Bernat02779b62016-04-03 13:48:43 +02001605 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001606
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 /* just after the address, a length may be specified */
1608 if (strcmp(args[arg+2], "len") == 0) {
1609 len = atoi(args[arg+3]);
1610 if (len < 80 || len > 65535) {
1611 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1612 file, linenum, args[arg+3]);
1613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616 logsrv->maxlen = len;
1617
1618 /* skip these two args */
1619 arg += 2;
1620 }
1621 else
1622 logsrv->maxlen = MAX_SYSLOG_LEN;
1623
1624 if (logsrv->maxlen > global.max_syslog_len) {
1625 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001626 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1627 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1628 logline = my_realloc2(logline, global.max_syslog_len + 1);
1629 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001630 }
1631
Dragan Dosen1322d092015-09-22 16:05:32 +02001632 /* after the length, a format may be specified */
1633 if (strcmp(args[arg+2], "format") == 0) {
1634 logsrv->format = get_log_format(args[arg+3]);
1635 if (logsrv->format < 0) {
1636 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1637 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001638 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001639 goto out;
1640 }
1641
1642 /* skip these two args */
1643 arg += 2;
1644 }
1645
David Carlier97880bb2016-04-08 10:35:26 +01001646 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1647 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001648 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001649 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001650
Willy Tarreau18324f52014-06-27 18:10:07 +02001651 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001652 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001653 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001655 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
1657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001659 if (*(args[arg+3])) {
1660 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001661 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001662 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001664 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666 }
1667
William Lallemand0f99e342011-10-12 17:50:54 +02001668 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001669 if (*(args[arg+4])) {
1670 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001671 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001672 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001674 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001675 }
1676 }
1677
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001678 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001679 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001680 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001681 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001682 free(logsrv);
1683 goto out;
1684 }
1685 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001686
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001687 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001688 if (port1 != port2) {
1689 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1690 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001691 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001692 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001693 goto out;
1694 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001695
William Lallemand0f99e342011-10-12 17:50:54 +02001696 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001697 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001698 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
William Lallemand0f99e342011-10-12 17:50:54 +02001701 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001702 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001703 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1704 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001705
1706 if (global.log_send_hostname != NULL) {
1707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1708 err_code |= ERR_ALERT;
1709 goto out;
1710 }
1711
1712 if (*(args[1]))
1713 name = args[1];
1714 else
1715 name = hostname;
1716
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001717 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001718 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001719 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001720 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1721 if (global.server_state_base != NULL) {
1722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1723 err_code |= ERR_ALERT;
1724 goto out;
1725 }
1726
1727 if (!*(args[1])) {
1728 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1729 err_code |= ERR_FATAL;
1730 goto out;
1731 }
1732
1733 global.server_state_base = strdup(args[1]);
1734 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001735 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1736 if (global.server_state_file != NULL) {
1737 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1738 err_code |= ERR_ALERT;
1739 goto out;
1740 }
1741
1742 if (!*(args[1])) {
1743 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1744 err_code |= ERR_FATAL;
1745 goto out;
1746 }
1747
1748 global.server_state_file = strdup(args[1]);
1749 }
Kevinm48936af2010-12-22 16:08:21 +00001750 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001751 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1752 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001753 if (*(args[1]) == 0) {
1754 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001758 chunk_destroy(&global.log_tag);
1759 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001760 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001761 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1763 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001764 if (global.spread_checks != 0) {
1765 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001766 err_code |= ERR_ALERT;
1767 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001768 }
1769 if (*(args[1]) == 0) {
1770 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001773 }
1774 global.spread_checks = atol(args[1]);
1775 if (global.spread_checks < 0 || global.spread_checks > 50) {
1776 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001780 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1781 const char *err;
1782 unsigned int val;
1783
William Lallemand1a748ae2015-05-19 16:37:23 +02001784 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1785 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001786 if (*(args[1]) == 0) {
1787 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
1792 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1793 if (err) {
1794 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 }
1797 global.max_spread_checks = val;
1798 if (global.max_spread_checks < 0) {
1799 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 }
1802 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1804#ifdef USE_CPU_AFFINITY
1805 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001806 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001807 unsigned long cpus = 0;
1808
1809 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001810 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001811 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001813 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 proc = atol(args[1]);
1817 if (proc >= 1 && proc <= LONGBITS)
1818 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001819 }
1820
1821 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001822 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1823 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 cur_arg = 2;
1829 while (*args[cur_arg]) {
1830 unsigned int low, high;
1831
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001832 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001833 char *dash = strchr(args[cur_arg], '-');
1834
1835 low = high = str2uic(args[cur_arg]);
1836 if (dash)
1837 high = str2uic(dash + 1);
1838
1839 if (high < low) {
1840 unsigned int swap = low;
1841 low = high;
1842 high = swap;
1843 }
1844
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001845 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001846 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001847 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851
1852 while (low <= high)
1853 cpus |= 1UL << low++;
1854 }
1855 else {
1856 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1857 file, linenum, args[0], args[cur_arg]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 cur_arg++;
1862 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001863 for (i = 0; i < LONGBITS; i++)
1864 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001865 global.cpu_map[i] = cpus;
1866#else
1867 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870#endif
1871 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001872 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1873 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1874 goto out;
1875
1876 if (*(args[2]) == 0) {
1877 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
1882 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1883 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1884 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 }
1888 }
1889 else if (!strcmp(args[0], "unsetenv")) {
1890 int arg;
1891
1892 if (*(args[1]) == 0) {
1893 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898 for (arg = 1; *args[arg]; arg++) {
1899 if (unsetenv(args[arg]) != 0) {
1900 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904 }
1905 }
1906 else if (!strcmp(args[0], "resetenv")) {
1907 extern char **environ;
1908 char **env = environ;
1909
1910 /* args contain variable names to keep, one per argument */
1911 while (*env) {
1912 int arg;
1913
1914 /* look for current variable in among all those we want to keep */
1915 for (arg = 1; *args[arg]; arg++) {
1916 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1917 (*env)[strlen(args[arg])] == '=')
1918 break;
1919 }
1920
1921 /* delete this variable */
1922 if (!*args[arg]) {
1923 char *delim = strchr(*env, '=');
1924
1925 if (!delim || delim - *env >= trash.size) {
1926 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930
1931 memcpy(trash.str, *env, delim - *env);
1932 trash.str[delim - *env] = 0;
1933
1934 if (unsetenv(trash.str) != 0) {
1935 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939 }
1940 else
1941 env++;
1942 }
1943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001945 struct cfg_kw_list *kwl;
1946 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001947 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001948
1949 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1950 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1951 if (kwl->kw[index].section != CFG_GLOBAL)
1952 continue;
1953 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001954 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001955 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001956 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001958 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001959 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001960 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001961 err_code |= ERR_WARN;
1962 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001963 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001964 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001965 }
1966 }
1967 }
1968
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001972
Willy Tarreau058e9072009-07-20 09:30:05 +02001973 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001974 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001975 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976}
1977
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001978void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001980 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 defproxy.mode = PR_MODE_TCP;
1982 defproxy.state = PR_STNEW;
1983 defproxy.maxconn = cfg_maxpconn;
1984 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001985 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001986
Simon Horman66183002013-02-23 10:16:43 +09001987 defproxy.defsrv.check.inter = DEF_CHKINTR;
1988 defproxy.defsrv.check.fastinter = 0;
1989 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001990 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1991 defproxy.defsrv.agent.fastinter = 0;
1992 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001993 defproxy.defsrv.check.rise = DEF_RISETIME;
1994 defproxy.defsrv.check.fall = DEF_FALLTIME;
1995 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1996 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001997 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001998 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001999 defproxy.defsrv.maxqueue = 0;
2000 defproxy.defsrv.minconn = 0;
2001 defproxy.defsrv.maxconn = 0;
2002 defproxy.defsrv.slowstart = 0;
2003 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2004 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2005 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002006
2007 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002008 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009}
2010
Willy Tarreauade5ec42010-01-28 19:33:49 +01002011
Willy Tarreau63af98d2014-05-18 08:11:41 +02002012/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2013 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2014 * ERR_FATAL in case of error.
2015 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002016static int create_cond_regex_rule(const char *file, int line,
2017 struct proxy *px, int dir, int action, int flags,
2018 const char *cmd, const char *reg, const char *repl,
2019 const char **cond_start)
2020{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002021 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002022 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002023 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002025 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002026 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002027 int cs;
2028 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002029
2030 if (px == &defproxy) {
2031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002032 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002033 goto err;
2034 }
2035
2036 if (*reg == 0) {
2037 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002038 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002039 goto err;
2040 }
2041
2042 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002043 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002044
Willy Tarreau5321c422010-01-28 20:35:13 +01002045 if (cond_start &&
2046 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002047 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2048 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2049 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002050 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002051 goto err;
2052 }
2053 }
2054 else if (cond_start && **cond_start) {
2055 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2056 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002057 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002058 goto err;
2059 }
2060
Willy Tarreau63af98d2014-05-18 08:11:41 +02002061 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002062 (dir == SMP_OPT_DIR_REQ) ?
2063 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2064 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2065 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002066
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002067 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002068 if (!preg) {
2069 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002070 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002071 goto err;
2072 }
2073
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002074 cs = !(flags & REG_ICASE);
2075 cap = !(flags & REG_NOSUB);
2076 error = NULL;
2077 if (!regex_comp(reg, preg, cs, cap, &error)) {
2078 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2079 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002080 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002081 goto err;
2082 }
2083
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002084 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002085 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002086 if (repl && err) {
2087 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2088 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002089 ret_code |= ERR_ALERT | ERR_FATAL;
2090 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002091 }
2092
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002093 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002094 ret_code |= ERR_WARN;
2095
2096 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002097
Willy Tarreau63af98d2014-05-18 08:11:41 +02002098 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002099 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002100 err:
2101 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002102 free(errmsg);
2103 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002104}
2105
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106/*
William Lallemand51097192015-04-14 16:35:22 +02002107 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002108 * Returns the error code, 0 if OK, or any combination of :
2109 * - ERR_ABORT: must abort ASAP
2110 * - ERR_FATAL: we can continue parsing but not start the service
2111 * - ERR_WARN: a warning has been emitted
2112 * - ERR_ALERT: an alert has been emitted
2113 * Only the two first ones can stop processing, the two others are just
2114 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002116int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2117{
2118 static struct peers *curpeers = NULL;
2119 struct peer *newpeer = NULL;
2120 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002121 struct bind_conf *bind_conf;
2122 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002123 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002124 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002125
2126 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002127 if (!*args[1]) {
2128 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002129 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002130 goto out;
2131 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002132
William Lallemand6e62fb62015-04-28 16:55:23 +02002133 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2134 goto out;
2135
Emeric Brun32da3c42010-09-23 18:39:19 +02002136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2139 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002140 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002141 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 }
2143
2144 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2145 /*
2146 * If there are two proxies with the same name only following
2147 * combinations are allowed:
2148 */
2149 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002150 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 +02002151 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002153 }
2154 }
2155
Vincent Bernat02779b62016-04-03 13:48:43 +02002156 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2158 err_code |= ERR_ALERT | ERR_ABORT;
2159 goto out;
2160 }
2161
2162 curpeers->next = peers;
2163 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002164 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 curpeers->conf.line = linenum;
2166 curpeers->last_change = now.tv_sec;
2167 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002168 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002169 }
2170 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002171 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002172 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002173 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002174
2175 if (!*args[2]) {
2176 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2177 file, linenum, args[0]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 err = invalid_char(args[1]);
2183 if (err) {
2184 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2185 file, linenum, *err, args[1]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
Vincent Bernat02779b62016-04-03 13:48:43 +02002190 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2192 err_code |= ERR_ALERT | ERR_ABORT;
2193 goto out;
2194 }
2195
2196 /* the peers are linked backwards first */
2197 curpeers->count++;
2198 newpeer->next = curpeers->remote;
2199 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002200 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002201 newpeer->conf.line = linenum;
2202
2203 newpeer->last_change = now.tv_sec;
2204 newpeer->id = strdup(args[1]);
2205
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002206 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002207 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002208 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002212
2213 proto = protocol_by_family(sk->ss_family);
2214 if (!proto || !proto->connect) {
2215 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2216 file, linenum, args[0], args[1]);
2217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
2219 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002220
2221 if (port1 != port2) {
2222 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2223 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
2226 }
2227
Willy Tarreau2aa38802013-02-20 19:20:59 +01002228 if (!port1) {
2229 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2230 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002234
Emeric Brun32da3c42010-09-23 18:39:19 +02002235 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002236 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002237 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002238 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002239
Emeric Brun32da3c42010-09-23 18:39:19 +02002240 if (strcmp(newpeer->id, localpeer) == 0) {
2241 /* Current is local peer, it define a frontend */
2242 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002243 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002244
2245 if (!curpeers->peers_fe) {
2246 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2247 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2248 err_code |= ERR_ALERT | ERR_ABORT;
2249 goto out;
2250 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002251
Willy Tarreau237250c2011-07-29 01:49:03 +02002252 init_new_proxy(curpeers->peers_fe);
2253 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002254 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002255 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2256 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002257 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002258
2259 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2260
Willy Tarreau902636f2013-03-10 19:44:48 +01002261 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2262 if (errmsg && *errmsg) {
2263 indent_msg(&errmsg, 2);
2264 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002265 }
2266 else
2267 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2268 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002269 err_code |= ERR_FATAL;
2270 goto out;
2271 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002272
2273 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002274 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002275 l->maxconn = curpeers->peers_fe->maxconn;
2276 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002277 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002278 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002279 l->analysers |= curpeers->peers_fe->fe_req_ana;
2280 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002281 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2282 global.maxsock += l->maxconn;
2283 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002284 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002285 else {
2286 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2287 file, linenum, args[0], args[1],
2288 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2289 err_code |= ERR_FATAL;
2290 goto out;
2291 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002292 }
2293 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002294 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2295 curpeers->state = PR_STSTOPPED;
2296 }
2297 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2298 curpeers->state = PR_STNEW;
2299 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002300 else if (*args[0] != 0) {
2301 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
2305
2306out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002307 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002308 return err_code;
2309}
2310
Baptiste Assmann325137d2015-04-13 23:40:55 +02002311/*
2312 * Parse a <resolvers> section.
2313 * Returns the error code, 0 if OK, or any combination of :
2314 * - ERR_ABORT: must abort ASAP
2315 * - ERR_FATAL: we can continue parsing but not start the service
2316 * - ERR_WARN: a warning has been emitted
2317 * - ERR_ALERT: an alert has been emitted
2318 * Only the two first ones can stop processing, the two others are just
2319 * indicators.
2320 */
2321int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2322{
2323 static struct dns_resolvers *curr_resolvers = NULL;
2324 struct dns_nameserver *newnameserver = NULL;
2325 const char *err;
2326 int err_code = 0;
2327 char *errmsg = NULL;
2328
2329 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2330 if (!*args[1]) {
2331 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2332 err_code |= ERR_ALERT | ERR_ABORT;
2333 goto out;
2334 }
2335
2336 err = invalid_char(args[1]);
2337 if (err) {
2338 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2339 file, linenum, *err, args[0], args[1]);
2340 err_code |= ERR_ALERT | ERR_ABORT;
2341 goto out;
2342 }
2343
2344 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2345 /* Error if two resolvers owns the same name */
2346 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2347 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2348 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2349 err_code |= ERR_ALERT | ERR_ABORT;
2350 }
2351 }
2352
Vincent Bernat02779b62016-04-03 13:48:43 +02002353 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002354 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2355 err_code |= ERR_ALERT | ERR_ABORT;
2356 goto out;
2357 }
2358
2359 /* default values */
2360 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2361 curr_resolvers->conf.file = strdup(file);
2362 curr_resolvers->conf.line = linenum;
2363 curr_resolvers->id = strdup(args[1]);
2364 curr_resolvers->query_ids = EB_ROOT;
2365 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002366 curr_resolvers->hold.valid = 10000;
2367 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002368 curr_resolvers->resolve_retries = 3;
2369 LIST_INIT(&curr_resolvers->nameserver_list);
2370 LIST_INIT(&curr_resolvers->curr_resolution);
2371 }
2372 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2373 struct sockaddr_storage *sk;
2374 int port1, port2;
2375 struct protocol *proto;
2376
2377 if (!*args[2]) {
2378 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2379 file, linenum, args[0]);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383
2384 err = invalid_char(args[1]);
2385 if (err) {
2386 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2387 file, linenum, *err, args[1]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
Baptiste Assmanna315c552015-11-02 22:55:49 +01002392 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2393 /* Error if two resolvers owns the same name */
2394 if (strcmp(newnameserver->id, args[1]) == 0) {
2395 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2396 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 }
2399 }
2400
Vincent Bernat02779b62016-04-03 13:48:43 +02002401 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2403 err_code |= ERR_ALERT | ERR_ABORT;
2404 goto out;
2405 }
2406
2407 /* the nameservers are linked backward first */
2408 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2409 curr_resolvers->count_nameservers++;
2410 newnameserver->resolvers = curr_resolvers;
2411 newnameserver->conf.file = strdup(file);
2412 newnameserver->conf.line = linenum;
2413 newnameserver->id = strdup(args[1]);
2414
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002415 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002416 if (!sk) {
2417 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
2422 proto = protocol_by_family(sk->ss_family);
2423 if (!proto || !proto->connect) {
2424 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2425 file, linenum, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 if (port1 != port2) {
2431 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2432 file, linenum, args[0], args[1], args[2]);
2433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
2435 }
2436
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002437 if (!port1 && !port2) {
2438 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2439 file, linenum, args[0], args[1]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
Baptiste Assmann325137d2015-04-13 23:40:55 +02002444 newnameserver->addr = *sk;
2445 }
2446 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2447 const char *res;
2448 unsigned int time;
2449
2450 if (!*args[2]) {
2451 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2452 file, linenum, args[0]);
2453 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2458 if (res) {
2459 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2460 file, linenum, *res, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464 if (strcmp(args[1], "valid") == 0)
2465 curr_resolvers->hold.valid = time;
2466 else {
2467 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2468 file, linenum, args[0], args[1]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
2473 }
2474 else if (strcmp(args[0], "resolve_retries") == 0) {
2475 if (!*args[1]) {
2476 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2477 file, linenum, args[0]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481 curr_resolvers->resolve_retries = atoi(args[1]);
2482 }
2483 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002484 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002485 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2486 file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002490 else if (strcmp(args[1], "retry") == 0) {
2491 const char *res;
2492 unsigned int timeout_retry;
2493
2494 if (!*args[2]) {
2495 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2496 file, linenum, args[0], args[1]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2501 if (res) {
2502 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2503 file, linenum, *res, args[0], args[1]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 curr_resolvers->timeout.retry = timeout_retry;
2508 }
2509 else {
2510 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2511 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002515 } /* neither "nameserver" nor "resolvers" */
2516 else if (*args[0] != 0) {
2517 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
2522 out:
2523 free(errmsg);
2524 return err_code;
2525}
Simon Horman0d16a402015-01-30 11:22:58 +09002526
2527/*
William Lallemand51097192015-04-14 16:35:22 +02002528 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002529 * Returns the error code, 0 if OK, or any combination of :
2530 * - ERR_ABORT: must abort ASAP
2531 * - ERR_FATAL: we can continue parsing but not start the service
2532 * - ERR_WARN: a warning has been emitted
2533 * - ERR_ALERT: an alert has been emitted
2534 * Only the two first ones can stop processing, the two others are just
2535 * indicators.
2536 */
2537int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2538{
2539 static struct mailers *curmailers = NULL;
2540 struct mailer *newmailer = NULL;
2541 const char *err;
2542 int err_code = 0;
2543 char *errmsg = NULL;
2544
2545 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2546 if (!*args[1]) {
2547 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2548 err_code |= ERR_ALERT | ERR_ABORT;
2549 goto out;
2550 }
2551
2552 err = invalid_char(args[1]);
2553 if (err) {
2554 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2555 file, linenum, *err, args[0], args[1]);
2556 err_code |= ERR_ALERT | ERR_ABORT;
2557 goto out;
2558 }
2559
2560 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2561 /*
2562 * If there are two proxies with the same name only following
2563 * combinations are allowed:
2564 */
2565 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002566 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 +09002567 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002569 }
2570 }
2571
Vincent Bernat02779b62016-04-03 13:48:43 +02002572 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2574 err_code |= ERR_ALERT | ERR_ABORT;
2575 goto out;
2576 }
2577
2578 curmailers->next = mailers;
2579 mailers = curmailers;
2580 curmailers->conf.file = strdup(file);
2581 curmailers->conf.line = linenum;
2582 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002583 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2584 * But need enough time so that timeouts don't occur
2585 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002586 }
2587 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2588 struct sockaddr_storage *sk;
2589 int port1, port2;
2590 struct protocol *proto;
2591
2592 if (!*args[2]) {
2593 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2594 file, linenum, args[0]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 err = invalid_char(args[1]);
2600 if (err) {
2601 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2602 file, linenum, *err, args[1]);
2603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
2605 }
2606
Vincent Bernat02779b62016-04-03 13:48:43 +02002607 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002608 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2609 err_code |= ERR_ALERT | ERR_ABORT;
2610 goto out;
2611 }
2612
2613 /* the mailers are linked backwards first */
2614 curmailers->count++;
2615 newmailer->next = curmailers->mailer_list;
2616 curmailers->mailer_list = newmailer;
2617 newmailer->mailers = curmailers;
2618 newmailer->conf.file = strdup(file);
2619 newmailer->conf.line = linenum;
2620
2621 newmailer->id = strdup(args[1]);
2622
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002623 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002624 if (!sk) {
2625 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
2628 }
2629
2630 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002631 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2632 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002633 file, linenum, args[0], args[1]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637
2638 if (port1 != port2) {
2639 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2640 file, linenum, args[0], args[1], args[2]);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 if (!port1) {
2646 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2647 file, linenum, args[0], args[1], args[2]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 newmailer->addr = *sk;
2653 newmailer->proto = proto;
2654 newmailer->xprt = &raw_sock;
2655 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002656 }
2657 else if (strcmp(args[0], "timeout") == 0) {
2658 if (!*args[1]) {
2659 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2660 file, linenum, args[0]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664 else if (strcmp(args[1], "mail") == 0) {
2665 const char *res;
2666 unsigned int timeout_mail;
2667 if (!*args[2]) {
2668 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2669 file, linenum, args[0], args[1]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2674 if (res) {
2675 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2676 file, linenum, *res, args[0]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680 if (timeout_mail <= 0) {
2681 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
2684 }
2685 curmailers->timeout.mail = timeout_mail;
2686 } else {
2687 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2688 file, linenum, args[0], args[1]);
2689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
2691 }
2692 }
Simon Horman0d16a402015-01-30 11:22:58 +09002693 else if (*args[0] != 0) {
2694 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
2699out:
2700 free(errmsg);
2701 return err_code;
2702}
2703
Simon Horman9dc49962015-01-30 11:22:59 +09002704static void free_email_alert(struct proxy *p)
2705{
2706 free(p->email_alert.mailers.name);
2707 p->email_alert.mailers.name = NULL;
2708 free(p->email_alert.from);
2709 p->email_alert.from = NULL;
2710 free(p->email_alert.to);
2711 p->email_alert.to = NULL;
2712 free(p->email_alert.myhostname);
2713 p->email_alert.myhostname = NULL;
2714}
2715
Willy Tarreau3842f002009-06-14 11:39:52 +02002716int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717{
2718 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002719 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002720 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002721 int rc;
2722 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002723 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002724 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002725 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002726 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002727 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 if (!strcmp(args[0], "listen"))
2730 rc = PR_CAP_LISTEN;
2731 else if (!strcmp(args[0], "frontend"))
2732 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002733 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 else
2736 rc = PR_CAP_NONE;
2737
2738 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 if (!*args[1]) {
2740 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2741 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2742 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_ABORT;
2744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002746
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002747 err = invalid_char(args[1]);
2748 if (err) {
2749 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2750 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002752 }
2753
Willy Tarreau8f50b682015-05-26 11:45:02 +02002754 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2755 if (curproxy) {
2756 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2757 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2758 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002760 }
2761
Vincent Bernat02779b62016-04-03 13:48:43 +02002762 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_ABORT;
2765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002767
Willy Tarreau97cb7802010-01-03 20:23:58 +01002768 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 curproxy->next = proxy;
2770 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002771 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2772 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002773 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002776 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777
William Lallemand6e62fb62015-04-28 16:55:23 +02002778 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2779 if (curproxy->cap & PR_CAP_FE)
2780 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783
2784 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002785 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002786 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002787
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002790 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002791 curproxy->no_options = defproxy.no_options;
2792 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002793 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002794 curproxy->except_net = defproxy.except_net;
2795 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002796 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002797 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002799 if (defproxy.fwdfor_hdr_len) {
2800 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2801 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2802 }
2803
Willy Tarreaub86db342009-11-30 11:50:16 +01002804 if (defproxy.orgto_hdr_len) {
2805 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2806 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2807 }
2808
Mark Lamourinec2247f02012-01-04 13:02:01 -05002809 if (defproxy.server_id_hdr_len) {
2810 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2811 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2812 }
2813
Willy Tarreau977b8e42006-12-29 14:19:17 +01002814 if (curproxy->cap & PR_CAP_FE) {
2815 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002816 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002817 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818
2819 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002820 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2821 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002822
2823 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825
Willy Tarreau977b8e42006-12-29 14:19:17 +01002826 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002827 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 curproxy->fullconn = defproxy.fullconn;
2829 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002830 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002831 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002833 if (defproxy.check_req) {
2834 curproxy->check_req = calloc(1, defproxy.check_len);
2835 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002837 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002839 if (defproxy.expect_str) {
2840 curproxy->expect_str = strdup(defproxy.expect_str);
2841 if (defproxy.expect_regex) {
2842 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002843 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2844 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002845 }
2846 }
2847
Willy Tarreau67402132012-05-31 20:40:20 +02002848 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002849 if (defproxy.cookie_name)
2850 curproxy->cookie_name = strdup(defproxy.cookie_name);
2851 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002852 if (defproxy.cookie_domain)
2853 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002854
Willy Tarreau31936852010-10-06 16:59:56 +02002855 if (defproxy.cookie_maxidle)
2856 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2857
2858 if (defproxy.cookie_maxlife)
2859 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2860
Emeric Brun647caf12009-06-30 17:57:00 +02002861 if (defproxy.rdp_cookie_name)
2862 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2863 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2864
Willy Tarreau01732802007-11-01 22:48:15 +01002865 if (defproxy.url_param_name)
2866 curproxy->url_param_name = strdup(defproxy.url_param_name);
2867 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002868
Benoitaffb4812009-03-25 13:02:10 +01002869 if (defproxy.hh_name)
2870 curproxy->hh_name = strdup(defproxy.hh_name);
2871 curproxy->hh_len = defproxy.hh_len;
2872 curproxy->hh_match_domain = defproxy.hh_match_domain;
2873
Willy Tarreauef9a3602012-12-08 22:29:20 +01002874 if (defproxy.conn_src.iface_name)
2875 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2876 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002877 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002878#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002879 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002880#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002881 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002884 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002885 if (defproxy.capture_name)
2886 curproxy->capture_name = strdup(defproxy.capture_name);
2887 curproxy->capture_namelen = defproxy.capture_namelen;
2888 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002892 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002893 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002894 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002895 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002896 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 curproxy->mon_net = defproxy.mon_net;
2898 curproxy->mon_mask = defproxy.mon_mask;
2899 if (defproxy.monitor_uri)
2900 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2901 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002902 if (defproxy.defbe.name)
2903 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002904
2905 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002906 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2907 if (curproxy->conf.logformat_string &&
2908 curproxy->conf.logformat_string != default_http_log_format &&
2909 curproxy->conf.logformat_string != default_tcp_log_format &&
2910 curproxy->conf.logformat_string != clf_http_log_format)
2911 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2912
2913 if (defproxy.conf.lfs_file) {
2914 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2915 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2916 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002917
2918 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2919 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2920 if (curproxy->conf.logformat_sd_string &&
2921 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2922 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2923
2924 if (defproxy.conf.lfsd_file) {
2925 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2926 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2927 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928 }
2929
2930 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002931 curproxy->timeout.connect = defproxy.timeout.connect;
2932 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002933 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002934 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002935 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002936 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002937 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002938 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002939 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002940 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002941 }
2942
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002944 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002945
2946 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002947 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002948 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002949 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002950 LIST_INIT(&node->list);
2951 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2952 }
2953
Willy Tarreau62a61232013-04-12 18:13:46 +02002954 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2955 if (curproxy->conf.uniqueid_format_string)
2956 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2957
Dragan Dosen43885c72015-10-01 13:18:13 +02002958 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002959
Willy Tarreau62a61232013-04-12 18:13:46 +02002960 if (defproxy.conf.uif_file) {
2961 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2962 curproxy->conf.uif_line = defproxy.conf.uif_line;
2963 }
William Lallemanda73203e2012-03-12 12:48:57 +01002964
2965 /* copy default header unique id */
2966 if (defproxy.header_unique_id)
2967 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2968
William Lallemand82fe75c2012-10-23 10:25:10 +02002969 /* default compression options */
2970 if (defproxy.comp != NULL) {
2971 curproxy->comp = calloc(1, sizeof(struct comp));
2972 curproxy->comp->algos = defproxy.comp->algos;
2973 curproxy->comp->types = defproxy.comp->types;
2974 }
2975
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002977 curproxy->conf.used_listener_id = EB_ROOT;
2978 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002979
Simon Horman98637e52014-06-20 12:30:16 +09002980 if (defproxy.check_path)
2981 curproxy->check_path = strdup(defproxy.check_path);
2982 if (defproxy.check_command)
2983 curproxy->check_command = strdup(defproxy.check_command);
2984
Simon Horman9dc49962015-01-30 11:22:59 +09002985 if (defproxy.email_alert.mailers.name)
2986 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2987 if (defproxy.email_alert.from)
2988 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2989 if (defproxy.email_alert.to)
2990 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2991 if (defproxy.email_alert.myhostname)
2992 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002993 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002994 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002995
Willy Tarreau93893792009-07-23 13:19:11 +02002996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 }
2998 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2999 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003000 /* FIXME-20070101: we should do this too at the end of the
3001 * config parsing to free all default values.
3002 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003003 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3004 err_code |= ERR_ABORT;
3005 goto out;
3006 }
3007
Willy Tarreaua534fea2008-08-03 12:19:50 +02003008 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003009 free(defproxy.check_command);
3010 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003011 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003012 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003013 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003014 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003015 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003016 free(defproxy.capture_name);
3017 free(defproxy.monitor_uri);
3018 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003019 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003020 free(defproxy.fwdfor_hdr_name);
3021 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003022 free(defproxy.orgto_hdr_name);
3023 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003024 free(defproxy.server_id_hdr_name);
3025 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003026 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003027 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003028 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003029 free(defproxy.expect_regex);
3030 defproxy.expect_regex = NULL;
3031 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003032
Willy Tarreau62a61232013-04-12 18:13:46 +02003033 if (defproxy.conf.logformat_string != default_http_log_format &&
3034 defproxy.conf.logformat_string != default_tcp_log_format &&
3035 defproxy.conf.logformat_string != clf_http_log_format)
3036 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003037
Willy Tarreau62a61232013-04-12 18:13:46 +02003038 free(defproxy.conf.uniqueid_format_string);
3039 free(defproxy.conf.lfs_file);
3040 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003041 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003042 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003043
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003044 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3045 free(defproxy.conf.logformat_sd_string);
3046 free(defproxy.conf.lfsd_file);
3047
Willy Tarreaua534fea2008-08-03 12:19:50 +02003048 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003049 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003050
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 /* we cannot free uri_auth because it might already be used */
3052 init_default_instance();
3053 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003054 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3055 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003056 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
3059 else if (curproxy == NULL) {
3060 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003064
3065 /* update the current file and line being parsed */
3066 curproxy->conf.args.file = curproxy->conf.file;
3067 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003068
3069 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003070 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3071 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3072 if (err_code & ERR_FATAL)
3073 goto out;
3074 }
3075 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003076 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003077 int cur_arg;
3078
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 if (curproxy == &defproxy) {
3080 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086
Willy Tarreau24709282013-03-10 21:32:12 +01003087 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003088 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003093
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003094 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003095
3096 /* use default settings for unix sockets */
3097 bind_conf->ux.uid = global.unix_bind.ux.uid;
3098 bind_conf->ux.gid = global.unix_bind.ux.gid;
3099 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003100
3101 /* NOTE: the following line might create several listeners if there
3102 * are comma-separated IPs or port ranges. So all further processing
3103 * will have to be applied to all listeners created after last_listen.
3104 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003105 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3106 if (errmsg && *errmsg) {
3107 indent_msg(&errmsg, 2);
3108 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003109 }
3110 else
3111 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3112 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003116
Willy Tarreau4348fad2012-09-20 16:48:07 +02003117 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3118 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003119 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003120 }
3121
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003122 cur_arg = 2;
3123 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003124 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003125 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003126 char *err;
3127
Willy Tarreau26982662012-09-12 23:17:10 +02003128 kw = bind_find_kw(args[cur_arg]);
3129 if (kw) {
3130 char *err = NULL;
3131 int code;
3132
3133 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003134 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3135 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003136 cur_arg += 1 + kw->skip ;
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
Willy Tarreau4348fad2012-09-20 16:48:07 +02003141 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003142 err_code |= code;
3143
3144 if (code) {
3145 if (err && *err) {
3146 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003147 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003148 }
3149 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003150 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3151 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003152 if (code & ERR_FATAL) {
3153 free(err);
3154 cur_arg += 1 + kw->skip;
3155 goto out;
3156 }
3157 }
3158 free(err);
3159 cur_arg += 1 + kw->skip;
3160 continue;
3161 }
3162
Willy Tarreau8638f482012-09-18 18:01:17 +02003163 err = NULL;
3164 if (!bind_dumped) {
3165 bind_dump_kws(&err);
3166 indent_msg(&err, 4);
3167 bind_dumped = 1;
3168 }
3169
3170 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3171 file, linenum, args[0], args[1], args[cur_arg],
3172 err ? " Registered keywords :" : "", err ? err : "");
3173 free(err);
3174
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003177 }
Willy Tarreau93893792009-07-23 13:19:11 +02003178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 }
3180 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003181 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003189
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 /* flush useless bits */
3191 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003194 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197
William Lallemanddf1425a2015-04-28 20:17:49 +02003198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3199 goto out;
3200
Willy Tarreau1c47f852006-07-09 08:22:27 +02003201 if (!*args[1]) {
3202 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003206 }
3207
Willy Tarreaua534fea2008-08-03 12:19:50 +02003208 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003209 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003210 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003211 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003212 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3213
Willy Tarreau93893792009-07-23 13:19:11 +02003214 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003217 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3218 goto out;
3219
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3221 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3222 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3223 else {
3224 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
3228 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003229 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003230 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003231
3232 if (curproxy == &defproxy) {
3233 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003237 }
3238
William Lallemanddf1425a2015-04-28 20:17:49 +02003239 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3240 goto out;
3241
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003242 if (!*args[1]) {
3243 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003247 }
3248
3249 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003250 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003251 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003252
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003253 if (curproxy->uuid <= 0) {
3254 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003255 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003258 }
3259
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003260 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3261 if (node) {
3262 struct proxy *target = container_of(node, struct proxy, conf.id);
3263 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3264 file, linenum, proxy_type_str(curproxy), curproxy->id,
3265 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003270 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003271 else if (!strcmp(args[0], "description")) {
3272 int i, len=0;
3273 char *d;
3274
Cyril Bonté99ed3272010-01-24 23:29:44 +01003275 if (curproxy == &defproxy) {
3276 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3277 file, linenum, args[0]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003282 if (!*args[1]) {
3283 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3284 file, linenum, args[0]);
3285 return -1;
3286 }
3287
Willy Tarreau348acfe2014-04-14 15:00:39 +02003288 for (i = 1; *args[i]; i++)
3289 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003290
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003291 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003292 curproxy->desc = d;
3293
Willy Tarreau348acfe2014-04-14 15:00:39 +02003294 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3295 for (i = 2; *args[i]; i++)
3296 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003297
3298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003300 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 curproxy->state = PR_STSTOPPED;
3303 }
3304 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003305 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 curproxy->state = PR_STNEW;
3308 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003309 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3310 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003311 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003312
3313 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003314 unsigned int low, high;
3315
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003316 if (strcmp(args[cur_arg], "all") == 0) {
3317 set = 0;
3318 break;
3319 }
3320 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003321 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003322 }
3323 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003324 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003325 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003326 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003327 char *dash = strchr(args[cur_arg], '-');
3328
3329 low = high = str2uic(args[cur_arg]);
3330 if (dash)
3331 high = str2uic(dash + 1);
3332
3333 if (high < low) {
3334 unsigned int swap = low;
3335 low = high;
3336 high = swap;
3337 }
3338
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003339 if (low < 1 || high > LONGBITS) {
3340 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3341 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003344 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003345 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003346 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003347 }
3348 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003349 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3350 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003353 }
3354 cur_arg++;
3355 }
3356 curproxy->bind_proc = set;
3357 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003358 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003359 if (curproxy == &defproxy) {
3360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003363 }
3364
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003365 err = invalid_char(args[1]);
3366 if (err) {
3367 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3368 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003370 }
3371
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003372 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003373 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3374 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003377 }
3378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3380 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381
Willy Tarreau977b8e42006-12-29 14:19:17 +01003382 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003384
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 if (*(args[1]) == 0) {
3386 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3387 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003388 err_code |= ERR_ALERT | ERR_FATAL;
3389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003391
Willy Tarreau67402132012-05-31 20:40:20 +02003392 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003393 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003394 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003395 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 curproxy->cookie_name = strdup(args[1]);
3397 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003398
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 cur_arg = 2;
3400 while (*(args[cur_arg])) {
3401 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003402 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003405 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003408 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
3410 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003411 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003414 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003416 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003417 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003420 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003422 else if (!strcmp(args[cur_arg], "httponly")) {
3423 curproxy->ck_opts |= PR_CK_HTTPONLY;
3424 }
3425 else if (!strcmp(args[cur_arg], "secure")) {
3426 curproxy->ck_opts |= PR_CK_SECURE;
3427 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003428 else if (!strcmp(args[cur_arg], "domain")) {
3429 if (!*args[cur_arg + 1]) {
3430 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3431 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003434 }
3435
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003436 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003437 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003438 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3439 " dots nor does not start with a dot."
3440 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003441 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003442 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003443 }
3444
3445 err = invalid_domainchar(args[cur_arg + 1]);
3446 if (err) {
3447 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3448 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003451 }
3452
Willy Tarreau68a897b2009-12-03 23:28:34 +01003453 if (!curproxy->cookie_domain) {
3454 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3455 } else {
3456 /* one domain was already specified, add another one by
3457 * building the string which will be returned along with
3458 * the cookie.
3459 */
3460 char *new_ptr;
3461 int new_len = strlen(curproxy->cookie_domain) +
3462 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3463 new_ptr = malloc(new_len);
3464 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3465 free(curproxy->cookie_domain);
3466 curproxy->cookie_domain = new_ptr;
3467 }
Willy Tarreau31936852010-10-06 16:59:56 +02003468 cur_arg++;
3469 }
3470 else if (!strcmp(args[cur_arg], "maxidle")) {
3471 unsigned int maxidle;
3472 const char *res;
3473
3474 if (!*args[cur_arg + 1]) {
3475 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3476 file, linenum, args[cur_arg]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480
3481 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3482 if (res) {
3483 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3484 file, linenum, *res, args[cur_arg]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 curproxy->cookie_maxidle = maxidle;
3489 cur_arg++;
3490 }
3491 else if (!strcmp(args[cur_arg], "maxlife")) {
3492 unsigned int maxlife;
3493 const char *res;
3494
3495 if (!*args[cur_arg + 1]) {
3496 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3497 file, linenum, args[cur_arg]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501
3502 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3503 if (res) {
3504 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3505 file, linenum, *res, args[cur_arg]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003510 cur_arg++;
3511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003513 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 +02003514 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518 cur_arg++;
3519 }
Willy Tarreau67402132012-05-31 20:40:20 +02003520 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525
Willy Tarreau67402132012-05-31 20:40:20 +02003526 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003531
Willy Tarreau67402132012-05-31 20:40:20 +02003532 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003533 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3534 file, linenum);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003538 else if (!strcmp(args[0], "email-alert")) {
3539 if (*(args[1]) == 0) {
3540 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3541 file, linenum, args[0]);
3542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
3544 }
3545
3546 if (!strcmp(args[1], "from")) {
3547 if (*(args[1]) == 0) {
3548 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3549 file, linenum, args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553 free(curproxy->email_alert.from);
3554 curproxy->email_alert.from = strdup(args[2]);
3555 }
3556 else if (!strcmp(args[1], "mailers")) {
3557 if (*(args[1]) == 0) {
3558 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3559 file, linenum, args[1]);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
3563 free(curproxy->email_alert.mailers.name);
3564 curproxy->email_alert.mailers.name = strdup(args[2]);
3565 }
3566 else if (!strcmp(args[1], "myhostname")) {
3567 if (*(args[1]) == 0) {
3568 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3569 file, linenum, args[1]);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
3573 free(curproxy->email_alert.myhostname);
3574 curproxy->email_alert.myhostname = strdup(args[2]);
3575 }
Simon Horman64e34162015-02-06 11:11:57 +09003576 else if (!strcmp(args[1], "level")) {
3577 curproxy->email_alert.level = get_log_level(args[2]);
3578 if (curproxy->email_alert.level < 0) {
3579 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3580 file, linenum, args[1], args[2]);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583 }
3584 }
Simon Horman9dc49962015-01-30 11:22:59 +09003585 else if (!strcmp(args[1], "to")) {
3586 if (*(args[1]) == 0) {
3587 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3588 file, linenum, args[1]);
3589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
3591 }
3592 free(curproxy->email_alert.to);
3593 curproxy->email_alert.to = strdup(args[2]);
3594 }
3595 else {
3596 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3597 file, linenum, args[1]);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
Simon Horman64e34162015-02-06 11:11:57 +09003601 /* Indicate that the email_alert is at least partially configured */
3602 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003603 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003604 else if (!strcmp(args[0], "external-check")) {
3605 if (*(args[1]) == 0) {
3606 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3607 file, linenum, args[0]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611
3612 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003613 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003614 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003615 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003616 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3617 file, linenum, args[1]);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
3621 free(curproxy->check_command);
3622 curproxy->check_command = strdup(args[2]);
3623 }
3624 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003625 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003626 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003627 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003628 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3629 file, linenum, args[1]);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633 free(curproxy->check_path);
3634 curproxy->check_path = strdup(args[2]);
3635 }
3636 else {
3637 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3638 file, linenum, args[1]);
3639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
3641 }
3642 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003643 else if (!strcmp(args[0], "persist")) { /* persist */
3644 if (*(args[1]) == 0) {
3645 Alert("parsing [%s:%d] : missing persist method.\n",
3646 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003649 }
3650
3651 if (!strncmp(args[1], "rdp-cookie", 10)) {
3652 curproxy->options2 |= PR_O2_RDPC_PRST;
3653
Emeric Brunb982a3d2010-01-04 15:45:53 +01003654 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003655 const char *beg, *end;
3656
3657 beg = args[1] + 11;
3658 end = strchr(beg, ')');
3659
William Lallemanddf1425a2015-04-28 20:17:49 +02003660 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3661 goto out;
3662
Emeric Brun647caf12009-06-30 17:57:00 +02003663 if (!end || end == beg) {
3664 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3665 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003668 }
3669
3670 free(curproxy->rdp_cookie_name);
3671 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3672 curproxy->rdp_cookie_len = end-beg;
3673 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003674 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003675 free(curproxy->rdp_cookie_name);
3676 curproxy->rdp_cookie_name = strdup("msts");
3677 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3678 }
3679 else { /* syntax */
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 else {
3687 Alert("parsing [%s:%d] : unknown persist method.\n",
3688 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003691 }
3692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003694 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003698 else if (!strcmp(args[0], "load-server-state-from-file")) {
3699 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3700 err_code |= ERR_WARN;
3701 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3702 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3703 }
3704 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3705 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3706 }
3707 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3708 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3709 }
3710 else {
3711 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3712 file, linenum, args[0], args[1]);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716 }
3717 else if (!strcmp(args[0], "server-state-file-name")) {
3718 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3719 err_code |= ERR_WARN;
3720 if (*(args[1]) == 0) {
3721 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3722 file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726 else if (!strcmp(args[1], "use-backend-name"))
3727 curproxy->server_state_file_name = strdup(curproxy->id);
3728 else
3729 curproxy->server_state_file_name = strdup(args[1]);
3730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003734
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003736 if (curproxy == &defproxy) {
3737 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741
William Lallemand1a748ae2015-05-19 16:37:23 +02003742 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3743 goto out;
3744
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 if (*(args[4]) == 0) {
3746 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003751 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 curproxy->capture_name = strdup(args[2]);
3753 curproxy->capture_namelen = strlen(curproxy->capture_name);
3754 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 curproxy->to_log |= LW_COOKIE;
3756 }
3757 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3758 struct cap_hdr *hdr;
3759
3760 if (curproxy == &defproxy) {
3761 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 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 }
3765
William Lallemand1a748ae2015-05-19 16:37:23 +02003766 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3767 goto out;
3768
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3770 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3771 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 }
3775
Vincent Bernat02779b62016-04-03 13:48:43 +02003776 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 hdr->next = curproxy->req_cap;
3778 hdr->name = strdup(args[3]);
3779 hdr->namelen = strlen(args[3]);
3780 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003781 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 hdr->index = curproxy->nb_req_cap++;
3783 curproxy->req_cap = hdr;
3784 curproxy->to_log |= LW_REQHDR;
3785 }
3786 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3787 struct cap_hdr *hdr;
3788
3789 if (curproxy == &defproxy) {
3790 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 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 }
3794
William Lallemand1a748ae2015-05-19 16:37:23 +02003795 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3796 goto out;
3797
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3799 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3800 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003804 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 hdr->next = curproxy->rsp_cap;
3806 hdr->name = strdup(args[3]);
3807 hdr->namelen = strlen(args[3]);
3808 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003809 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 hdr->index = curproxy->nb_rsp_cap++;
3811 curproxy->rsp_cap = hdr;
3812 curproxy->to_log |= LW_RSPHDR;
3813 }
3814 else {
3815 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3816 file, linenum, args[0]);
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 }
3820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003824
William Lallemanddf1425a2015-04-28 20:17:49 +02003825 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3826 goto out;
3827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 if (*(args[1]) == 0) {
3829 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3830 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
3834 curproxy->conn_retries = atol(args[1]);
3835 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003836 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003837 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003838
3839 if (curproxy == &defproxy) {
3840 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844
Willy Tarreau20b0de52012-12-24 15:45:22 +01003845 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003846 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003847 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3848 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3849 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3850 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003851 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 +01003852 file, linenum, args[0]);
3853 err_code |= ERR_WARN;
3854 }
3855
Willy Tarreauff011f22011-01-06 17:51:27 +01003856 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003857
Willy Tarreauff011f22011-01-06 17:51:27 +01003858 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003859 err_code |= ERR_ALERT | ERR_ABORT;
3860 goto out;
3861 }
3862
Willy Tarreau5002f572014-04-23 01:32:02 +02003863 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003864 err_code |= warnif_cond_conflicts(rule->cond,
3865 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3866 file, linenum);
3867
Willy Tarreauff011f22011-01-06 17:51:27 +01003868 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003869 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003870 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003871 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003872
3873 if (curproxy == &defproxy) {
3874 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878
3879 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003880 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003881 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3882 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003883 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3884 file, linenum, args[0]);
3885 err_code |= ERR_WARN;
3886 }
3887
3888 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3889
3890 if (!rule) {
3891 err_code |= ERR_ALERT | ERR_ABORT;
3892 goto out;
3893 }
3894
3895 err_code |= warnif_cond_conflicts(rule->cond,
3896 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3897 file, linenum);
3898
3899 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3900 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003901 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3902 /* set the header name and length into the proxy structure */
3903 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3904 err_code |= ERR_WARN;
3905
3906 if (!*args[1]) {
3907 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3908 file, linenum, args[0]);
3909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
3911 }
3912
3913 /* set the desired header name */
3914 free(curproxy->server_id_hdr_name);
3915 curproxy->server_id_hdr_name = strdup(args[1]);
3916 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3917 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003918 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003919 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003920
Willy Tarreaub099aca2008-10-12 17:26:37 +02003921 if (curproxy == &defproxy) {
3922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003925 }
3926
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003927 /* emulate "block" using "http-request block". Since these rules are supposed to
3928 * be processed before all http-request rules, we put them into their own list
3929 * and will insert them at the end.
3930 */
3931 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3932 if (!rule) {
3933 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003934 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003935 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003936 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3937 err_code |= warnif_cond_conflicts(rule->cond,
3938 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3939 file, linenum);
3940 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003941
3942 if (!already_warned(WARN_BLOCK_DEPRECATED))
3943 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]);
3944
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003945 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003946 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003947 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003948
Cyril Bonté99ed3272010-01-24 23:29:44 +01003949 if (curproxy == &defproxy) {
3950 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
3953 }
3954
Willy Tarreaube4653b2015-05-28 15:26:58 +02003955 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003956 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3957 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003960 }
3961
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003962 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003963 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003964 err_code |= warnif_cond_conflicts(rule->cond,
3965 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3966 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003967 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003968 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003969 struct switching_rule *rule;
3970
Willy Tarreaub099aca2008-10-12 17:26:37 +02003971 if (curproxy == &defproxy) {
3972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003975 }
3976
Willy Tarreau55ea7572007-06-17 19:56:27 +02003977 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003979
3980 if (*(args[1]) == 0) {
3981 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003984 }
3985
Willy Tarreauf51658d2014-04-23 01:21:56 +02003986 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3987 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3988 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3989 file, linenum, errmsg);
3990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003993
Willy Tarreauf51658d2014-04-23 01:21:56 +02003994 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003995 }
3996
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003997 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02003998 rule->cond = cond;
3999 rule->be.name = strdup(args[1]);
4000 LIST_INIT(&rule->list);
4001 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4002 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004003 else if (strcmp(args[0], "use-server") == 0) {
4004 struct server_rule *rule;
4005
4006 if (curproxy == &defproxy) {
4007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011
4012 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4013 err_code |= ERR_WARN;
4014
4015 if (*(args[1]) == 0) {
4016 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
4021 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4022 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4023 file, linenum, args[0]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004028 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4029 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4030 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004035 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004036
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004037 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004038 rule->cond = cond;
4039 rule->srv.name = strdup(args[1]);
4040 LIST_INIT(&rule->list);
4041 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4042 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4043 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004044 else if ((!strcmp(args[0], "force-persist")) ||
4045 (!strcmp(args[0], "ignore-persist"))) {
4046 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004047
4048 if (curproxy == &defproxy) {
4049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053
4054 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4055 err_code |= ERR_WARN;
4056
Willy Tarreauef6494c2010-01-28 17:12:36 +01004057 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004058 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4059 file, linenum, args[0]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004064 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4065 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4066 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004071 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4072 * where force-persist is applied.
4073 */
4074 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004075
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004076 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004077 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004078 if (!strcmp(args[0], "force-persist")) {
4079 rule->type = PERSIST_TYPE_FORCE;
4080 } else {
4081 rule->type = PERSIST_TYPE_IGNORE;
4082 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004083 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004084 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004085 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 else if (!strcmp(args[0], "stick-table")) {
4087 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004088 struct proxy *other;
4089
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004090 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004091 if (other) {
4092 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4093 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004097
Emeric Brun32da3c42010-09-23 18:39:19 +02004098 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 curproxy->table.type = (unsigned int)-1;
4100 while (*args[myidx]) {
4101 const char *err;
4102
4103 if (strcmp(args[myidx], "size") == 0) {
4104 myidx++;
4105 if (!*(args[myidx])) {
4106 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4107 file, linenum, args[myidx-1]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4112 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4113 file, linenum, *err, args[myidx-1]);
4114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004117 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004119 else if (strcmp(args[myidx], "peers") == 0) {
4120 myidx++;
Godbach50523162013-12-11 19:48:57 +08004121 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004122 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;
Godbach50523162013-12-11 19:48:57 +08004126 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004127 curproxy->table.peers.name = strdup(args[myidx++]);
4128 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004129 else if (strcmp(args[myidx], "expire") == 0) {
4130 myidx++;
4131 if (!*(args[myidx])) {
4132 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4133 file, linenum, args[myidx-1]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4138 if (err) {
4139 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4140 file, linenum, *err, args[myidx-1]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
4143 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004144 if (val > INT_MAX) {
4145 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4146 file, linenum, val);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004151 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 }
4153 else if (strcmp(args[myidx], "nopurge") == 0) {
4154 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004155 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 }
4157 else if (strcmp(args[myidx], "type") == 0) {
4158 myidx++;
4159 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4160 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4161 file, linenum, args[myidx]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004165 /* myidx already points to next arg */
4166 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004167 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004168 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004169 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004170
4171 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004172 nw = args[myidx];
4173 while (*nw) {
4174 /* the "store" keyword supports a comma-separated list */
4175 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004176 sa = NULL; /* store arg */
4177 while (*nw && *nw != ',') {
4178 if (*nw == '(') {
4179 *nw = 0;
4180 sa = ++nw;
4181 while (*nw != ')') {
4182 if (!*nw) {
4183 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4184 file, linenum, args[0], cw);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188 nw++;
4189 }
4190 *nw = '\0';
4191 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004192 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004193 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004194 if (*nw)
4195 *nw++ = '\0';
4196 type = stktable_get_data_type(cw);
4197 if (type < 0) {
4198 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4199 file, linenum, args[0], cw);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
Willy Tarreauac782882010-06-20 10:41:54 +02004203
4204 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4205 switch (err) {
4206 case PE_NONE: break;
4207 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004208 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4209 file, linenum, args[0], cw);
4210 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004211 break;
4212
4213 case PE_ARG_MISSING:
4214 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4215 file, linenum, args[0], cw);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218
4219 case PE_ARG_NOT_USED:
4220 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4221 file, linenum, args[0], cw);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224
4225 default:
4226 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4227 file, linenum, args[0], cw);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004230 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004231 }
4232 myidx++;
4233 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004234 else {
4235 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4236 file, linenum, args[myidx]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004240 }
4241
4242 if (!curproxy->table.size) {
4243 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4244 file, linenum);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 if (curproxy->table.type == (unsigned int)-1) {
4250 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4251 file, linenum);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255 }
4256 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004257 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004258 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 int myidx = 0;
4260 const char *name = NULL;
4261 int flags;
4262
4263 if (curproxy == &defproxy) {
4264 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268
4269 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4270 err_code |= ERR_WARN;
4271 goto out;
4272 }
4273
4274 myidx++;
4275 if ((strcmp(args[myidx], "store") == 0) ||
4276 (strcmp(args[myidx], "store-request") == 0)) {
4277 myidx++;
4278 flags = STK_IS_STORE;
4279 }
4280 else if (strcmp(args[myidx], "store-response") == 0) {
4281 myidx++;
4282 flags = STK_IS_STORE | STK_ON_RSP;
4283 }
4284 else if (strcmp(args[myidx], "match") == 0) {
4285 myidx++;
4286 flags = STK_IS_MATCH;
4287 }
4288 else if (strcmp(args[myidx], "on") == 0) {
4289 myidx++;
4290 flags = STK_IS_MATCH | STK_IS_STORE;
4291 }
4292 else {
4293 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297
4298 if (*(args[myidx]) == 0) {
4299 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004304 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004305 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004306 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004307 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311
4312 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004313 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4314 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4315 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004317 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 goto out;
4319 }
4320 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004321 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4322 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4323 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004324 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004325 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004326 goto out;
4327 }
4328 }
4329
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004330 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004331 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004332
Emeric Brunb982a3d2010-01-04 15:45:53 +01004333 if (strcmp(args[myidx], "table") == 0) {
4334 myidx++;
4335 name = args[myidx++];
4336 }
4337
Willy Tarreauef6494c2010-01-28 17:12:36 +01004338 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004339 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4340 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4341 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004342 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004343 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004344 goto out;
4345 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004346 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004347 else if (*(args[myidx])) {
4348 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4349 file, linenum, args[0], args[myidx]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004351 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004352 goto out;
4353 }
Emeric Brun97679e72010-09-23 17:56:44 +02004354 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004355 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004356 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004357 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004358
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004359 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004360 rule->cond = cond;
4361 rule->expr = expr;
4362 rule->flags = flags;
4363 rule->table.name = name ? strdup(name) : NULL;
4364 LIST_INIT(&rule->list);
4365 if (flags & STK_ON_RSP)
4366 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4367 else
4368 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 else if (!strcmp(args[0], "stats")) {
4371 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4372 curproxy->uri_auth = NULL; /* we must detach from the default config */
4373
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004374 if (!*args[1]) {
4375 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004376 } else if (!strcmp(args[1], "admin")) {
4377 struct stats_admin_rule *rule;
4378
4379 if (curproxy == &defproxy) {
4380 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
4384
4385 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4386 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4387 err_code |= ERR_ALERT | ERR_ABORT;
4388 goto out;
4389 }
4390
4391 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4392 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4393 file, linenum, args[0], args[1]);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004397 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4398 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4399 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
4403
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004404 err_code |= warnif_cond_conflicts(cond,
4405 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4406 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004407
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004408 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004409 rule->cond = cond;
4410 LIST_INIT(&rule->list);
4411 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 } else if (!strcmp(args[1], "uri")) {
4413 if (*(args[2]) == 0) {
4414 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004419 err_code |= ERR_ALERT | ERR_ABORT;
4420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 }
4422 } else if (!strcmp(args[1], "realm")) {
4423 if (*(args[2]) == 0) {
4424 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_ABORT;
4430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004432 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004433 unsigned interval;
4434
4435 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4436 if (err) {
4437 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4438 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004441 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_ABORT;
4444 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004445 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004446 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004447 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004448
4449 if (curproxy == &defproxy) {
4450 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
4454
4455 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4456 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4457 err_code |= ERR_ALERT | ERR_ABORT;
4458 goto out;
4459 }
4460
Willy Tarreauff011f22011-01-06 17:51:27 +01004461 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004462 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004463 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4464 file, linenum, args[0]);
4465 err_code |= ERR_WARN;
4466 }
4467
Willy Tarreauff011f22011-01-06 17:51:27 +01004468 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004469
Willy Tarreauff011f22011-01-06 17:51:27 +01004470 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
4473 }
4474
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004475 err_code |= warnif_cond_conflicts(rule->cond,
4476 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4477 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004478 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004479
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 } else if (!strcmp(args[1], "auth")) {
4481 if (*(args[2]) == 0) {
4482 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4486 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
4490 } else if (!strcmp(args[1], "scope")) {
4491 if (*(args[2]) == 0) {
4492 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_ALERT | ERR_ABORT;
4498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
4500 } else if (!strcmp(args[1], "enable")) {
4501 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004506 } else if (!strcmp(args[1], "hide-version")) {
4507 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_ABORT;
4510 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004511 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004512 } else if (!strcmp(args[1], "show-legends")) {
4513 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4514 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4515 err_code |= ERR_ALERT | ERR_ABORT;
4516 goto out;
4517 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004518 } else if (!strcmp(args[1], "show-node")) {
4519
4520 if (*args[2]) {
4521 int i;
4522 char c;
4523
4524 for (i=0; args[2][i]; i++) {
4525 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004526 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4527 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528 break;
4529 }
4530
4531 if (!i || args[2][i]) {
4532 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4533 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4534 file, linenum, args[0], args[1]);
4535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
4538 }
4539
4540 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4542 err_code |= ERR_ALERT | ERR_ABORT;
4543 goto out;
4544 }
4545 } else if (!strcmp(args[1], "show-desc")) {
4546 char *desc = NULL;
4547
4548 if (*args[2]) {
4549 int i, len=0;
4550 char *d;
4551
Willy Tarreau348acfe2014-04-14 15:00:39 +02004552 for (i = 2; *args[i]; i++)
4553 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004554
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004555 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004556
Willy Tarreau348acfe2014-04-14 15:00:39 +02004557 d += snprintf(d, desc + len - d, "%s", args[2]);
4558 for (i = 3; *args[i]; i++)
4559 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004560 }
4561
4562 if (!*args[2] && !global.desc)
4563 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4564 file, linenum, args[1]);
4565 else {
4566 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4567 free(desc);
4568 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4569 err_code |= ERR_ALERT | ERR_ABORT;
4570 goto out;
4571 }
4572 free(desc);
4573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004575stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004576 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 +01004577 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 }
4581 }
4582 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004583 int optnum;
4584
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004585 if (*(args[1]) == '\0') {
4586 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4587 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004591
4592 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4593 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004594 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4595 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4596 file, linenum, cfg_opts[optnum].name);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004600 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4601 goto out;
4602
Willy Tarreau93893792009-07-23 13:19:11 +02004603 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4604 err_code |= ERR_WARN;
4605 goto out;
4606 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004607
Willy Tarreau3842f002009-06-14 11:39:52 +02004608 curproxy->no_options &= ~cfg_opts[optnum].val;
4609 curproxy->options &= ~cfg_opts[optnum].val;
4610
4611 switch (kwm) {
4612 case KWM_STD:
4613 curproxy->options |= cfg_opts[optnum].val;
4614 break;
4615 case KWM_NO:
4616 curproxy->no_options |= cfg_opts[optnum].val;
4617 break;
4618 case KWM_DEF: /* already cleared */
4619 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004620 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004621
Willy Tarreau93893792009-07-23 13:19:11 +02004622 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004623 }
4624 }
4625
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004626 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4627 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004628 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4629 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4630 file, linenum, cfg_opts2[optnum].name);
4631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004634 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4635 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004636 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4637 err_code |= ERR_WARN;
4638 goto out;
4639 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004640
Willy Tarreau3842f002009-06-14 11:39:52 +02004641 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4642 curproxy->options2 &= ~cfg_opts2[optnum].val;
4643
4644 switch (kwm) {
4645 case KWM_STD:
4646 curproxy->options2 |= cfg_opts2[optnum].val;
4647 break;
4648 case KWM_NO:
4649 curproxy->no_options2 |= cfg_opts2[optnum].val;
4650 break;
4651 case KWM_DEF: /* already cleared */
4652 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004653 }
Willy Tarreau93893792009-07-23 13:19:11 +02004654 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004655 }
4656 }
4657
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004658 /* HTTP options override each other. They can be cancelled using
4659 * "no option xxx" which only switches to default mode if the mode
4660 * was this one (useful for cancelling options set in defaults
4661 * sections).
4662 */
4663 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004664 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4665 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004666 if (kwm == KWM_STD) {
4667 curproxy->options &= ~PR_O_HTTP_MODE;
4668 curproxy->options |= PR_O_HTTP_PCL;
4669 goto out;
4670 }
4671 else if (kwm == KWM_NO) {
4672 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4673 curproxy->options &= ~PR_O_HTTP_MODE;
4674 goto out;
4675 }
4676 }
4677 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004678 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4679 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004680 if (kwm == KWM_STD) {
4681 curproxy->options &= ~PR_O_HTTP_MODE;
4682 curproxy->options |= PR_O_HTTP_FCL;
4683 goto out;
4684 }
4685 else if (kwm == KWM_NO) {
4686 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4687 curproxy->options &= ~PR_O_HTTP_MODE;
4688 goto out;
4689 }
4690 }
4691 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004692 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4693 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004694 if (kwm == KWM_STD) {
4695 curproxy->options &= ~PR_O_HTTP_MODE;
4696 curproxy->options |= PR_O_HTTP_SCL;
4697 goto out;
4698 }
4699 else if (kwm == KWM_NO) {
4700 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4701 curproxy->options &= ~PR_O_HTTP_MODE;
4702 goto out;
4703 }
4704 }
4705 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004706 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4707 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004708 if (kwm == KWM_STD) {
4709 curproxy->options &= ~PR_O_HTTP_MODE;
4710 curproxy->options |= PR_O_HTTP_KAL;
4711 goto out;
4712 }
4713 else if (kwm == KWM_NO) {
4714 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4715 curproxy->options &= ~PR_O_HTTP_MODE;
4716 goto out;
4717 }
4718 }
4719 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004720 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4721 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004722 if (kwm == KWM_STD) {
4723 curproxy->options &= ~PR_O_HTTP_MODE;
4724 curproxy->options |= PR_O_HTTP_TUN;
4725 goto out;
4726 }
4727 else if (kwm == KWM_NO) {
4728 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4729 curproxy->options &= ~PR_O_HTTP_MODE;
4730 goto out;
4731 }
4732 }
4733
Joseph Lynch726ab712015-05-11 23:25:34 -07004734 /* Redispatch can take an integer argument that control when the
4735 * resispatch occurs. All values are relative to the retries option.
4736 * This can be cancelled using "no option xxx".
4737 */
4738 if (strcmp(args[1], "redispatch") == 0) {
4739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4740 err_code |= ERR_WARN;
4741 goto out;
4742 }
4743
4744 curproxy->no_options &= ~PR_O_REDISP;
4745 curproxy->options &= ~PR_O_REDISP;
4746
4747 switch (kwm) {
4748 case KWM_STD:
4749 curproxy->options |= PR_O_REDISP;
4750 curproxy->redispatch_after = -1;
4751 if(*args[2]) {
4752 curproxy->redispatch_after = atol(args[2]);
4753 }
4754 break;
4755 case KWM_NO:
4756 curproxy->no_options |= PR_O_REDISP;
4757 curproxy->redispatch_after = 0;
4758 break;
4759 case KWM_DEF: /* already cleared */
4760 break;
4761 }
4762 goto out;
4763 }
4764
Willy Tarreau3842f002009-06-14 11:39:52 +02004765 if (kwm != KWM_STD) {
4766 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004767 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004768 err_code |= ERR_ALERT | ERR_FATAL;
4769 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004770 }
4771
Emeric Brun3a058f32009-06-30 18:26:00 +02004772 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004773 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004775 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004776 if (*(args[2]) != '\0') {
4777 if (!strcmp(args[2], "clf")) {
4778 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004779 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004780 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004781 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004784 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004785 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4786 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004787 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004788 if (curproxy->conf.logformat_string != default_http_log_format &&
4789 curproxy->conf.logformat_string != default_tcp_log_format &&
4790 curproxy->conf.logformat_string != clf_http_log_format)
4791 free(curproxy->conf.logformat_string);
4792 curproxy->conf.logformat_string = logformat;
4793
4794 free(curproxy->conf.lfs_file);
4795 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4796 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004797 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004798 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004800 if (curproxy->conf.logformat_string != default_http_log_format &&
4801 curproxy->conf.logformat_string != default_tcp_log_format &&
4802 curproxy->conf.logformat_string != clf_http_log_format)
4803 free(curproxy->conf.logformat_string);
4804 curproxy->conf.logformat_string = default_tcp_log_format;
4805
4806 free(curproxy->conf.lfs_file);
4807 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4808 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004809
4810 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4811 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004814 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004815 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004816 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004817
William Lallemanddf1425a2015-04-28 20:17:49 +02004818 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4819 goto out;
4820
Willy Tarreau13943ab2006-12-31 00:24:10 +01004821 if (curproxy->cap & PR_CAP_FE)
4822 curproxy->options |= PR_O_TCP_CLI_KA;
4823 if (curproxy->cap & PR_CAP_BE)
4824 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
4826 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004828 err_code |= ERR_WARN;
4829
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004831 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004832 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004833 curproxy->options2 &= ~PR_O2_CHK_ANY;
4834 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 if (!*args[2]) { /* no argument */
4836 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4837 curproxy->check_len = strlen(DEF_CHECK_REQ);
4838 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004839 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004840 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004842 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004844 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 if (*args[4])
4846 reqlen += strlen(args[4]);
4847 else
4848 reqlen += strlen("HTTP/1.0");
4849
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004850 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004852 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004854 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4855 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004856 }
4857 else if (!strcmp(args[1], "ssl-hello-chk")) {
4858 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004861
Willy Tarreaua534fea2008-08-03 12:19:50 +02004862 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004863 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004864 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004865 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004866
4867 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
Willy Tarreau23677902007-05-08 23:50:35 +02004870 else if (!strcmp(args[1], "smtpchk")) {
4871 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004872 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004873 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004874 curproxy->options2 &= ~PR_O2_CHK_ANY;
4875 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004876
4877 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4878 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4879 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4880 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4881 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4882 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004883 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004884 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4885 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4886 } else {
4887 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4888 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4889 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4890 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4891 }
4892 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004893 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4894 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004895 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004896 else if (!strcmp(args[1], "pgsql-check")) {
4897 /* use PostgreSQL request to check servers' health */
4898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4899 err_code |= ERR_WARN;
4900
4901 free(curproxy->check_req);
4902 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004903 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004904 curproxy->options2 |= PR_O2_PGSQL_CHK;
4905
4906 if (*(args[2])) {
4907 int cur_arg = 2;
4908
4909 while (*(args[cur_arg])) {
4910 if (strcmp(args[cur_arg], "user") == 0) {
4911 char * packet;
4912 uint32_t packet_len;
4913 uint32_t pv;
4914
4915 /* suboption header - needs additional argument for it */
4916 if (*(args[cur_arg+1]) == 0) {
4917 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4918 file, linenum, args[0], args[1], args[cur_arg]);
4919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
4921 }
4922
4923 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4924 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4925 pv = htonl(0x30000); /* protocol version 3.0 */
4926
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004927 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004928
4929 memcpy(packet + 4, &pv, 4);
4930
4931 /* copy "user" */
4932 memcpy(packet + 8, "user", 4);
4933
4934 /* copy username */
4935 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4936
4937 free(curproxy->check_req);
4938 curproxy->check_req = packet;
4939 curproxy->check_len = packet_len;
4940
4941 packet_len = htonl(packet_len);
4942 memcpy(packet, &packet_len, 4);
4943 cur_arg += 2;
4944 } else {
4945 /* unknown suboption - catchall */
4946 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4947 file, linenum, args[0], args[1]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951 } /* end while loop */
4952 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004953 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4954 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004955 }
4956
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004957 else if (!strcmp(args[1], "redis-check")) {
4958 /* use REDIS PING request to check servers' health */
4959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4960 err_code |= ERR_WARN;
4961
4962 free(curproxy->check_req);
4963 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004964 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004965 curproxy->options2 |= PR_O2_REDIS_CHK;
4966
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004967 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004968 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4969 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004970
4971 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4972 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004973 }
4974
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004975 else if (!strcmp(args[1], "mysql-check")) {
4976 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4978 err_code |= ERR_WARN;
4979
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004980 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004981 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004982 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004983 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004984
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004985 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004986 * const char mysql40_client_auth_pkt[] = {
4987 * "\x0e\x00\x00" // packet length
4988 * "\x01" // packet number
4989 * "\x00\x00" // client capabilities
4990 * "\x00\x00\x01" // max packet
4991 * "haproxy\x00" // username (null terminated string)
4992 * "\x00" // filler (always 0x00)
4993 * "\x01\x00\x00" // packet length
4994 * "\x00" // packet number
4995 * "\x01" // COM_QUIT command
4996 * };
4997 */
4998
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004999 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5000 * const char mysql41_client_auth_pkt[] = {
5001 * "\x0e\x00\x00\" // packet length
5002 * "\x01" // packet number
5003 * "\x00\x00\x00\x00" // client capabilities
5004 * "\x00\x00\x00\x01" // max packet
5005 * "\x21" // character set (UTF-8)
5006 * char[23] // All zeroes
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
5015
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005016 if (*(args[2])) {
5017 int cur_arg = 2;
5018
5019 while (*(args[cur_arg])) {
5020 if (strcmp(args[cur_arg], "user") == 0) {
5021 char *mysqluser;
5022 int packetlen, reqlen, userlen;
5023
5024 /* suboption header - needs additional argument for it */
5025 if (*(args[cur_arg+1]) == 0) {
5026 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5027 file, linenum, args[0], args[1], args[cur_arg]);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
5031 mysqluser = args[cur_arg + 1];
5032 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005033
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005034 if (*(args[cur_arg+2])) {
5035 if (!strcmp(args[cur_arg+2], "post-41")) {
5036 packetlen = userlen + 7 + 27;
5037 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005038
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005039 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005040 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005041 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005042
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005043 snprintf(curproxy->check_req, 4, "%c%c%c",
5044 ((unsigned char) packetlen & 0xff),
5045 ((unsigned char) (packetlen >> 8) & 0xff),
5046 ((unsigned char) (packetlen >> 16) & 0xff));
5047
5048 curproxy->check_req[3] = 1;
5049 curproxy->check_req[5] = 130;
5050 curproxy->check_req[11] = 1;
5051 curproxy->check_req[12] = 33;
5052 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5053 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5054 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5055 cur_arg += 3;
5056 } else {
5057 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
5060 }
5061 } else {
5062 packetlen = userlen + 7;
5063 reqlen = packetlen + 9;
5064
5065 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005066 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005067 curproxy->check_len = reqlen;
5068
5069 snprintf(curproxy->check_req, 4, "%c%c%c",
5070 ((unsigned char) packetlen & 0xff),
5071 ((unsigned char) (packetlen >> 8) & 0xff),
5072 ((unsigned char) (packetlen >> 16) & 0xff));
5073
5074 curproxy->check_req[3] = 1;
5075 curproxy->check_req[5] = 128;
5076 curproxy->check_req[8] = 1;
5077 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5078 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5079 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5080 cur_arg += 2;
5081 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005082 } else {
5083 /* unknown suboption - catchall */
5084 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5085 file, linenum, args[0], args[1]);
5086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
5089 } /* end while loop */
5090 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005091 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005092 else if (!strcmp(args[1], "ldap-check")) {
5093 /* use LDAP request to check servers' health */
5094 free(curproxy->check_req);
5095 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005096 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005097 curproxy->options2 |= PR_O2_LDAP_CHK;
5098
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005099 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005100 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5101 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005102 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5103 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005104 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005105 else if (!strcmp(args[1], "tcp-check")) {
5106 /* use raw TCPCHK send/expect to check servers' health */
5107 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5108 err_code |= ERR_WARN;
5109
5110 free(curproxy->check_req);
5111 curproxy->check_req = NULL;
5112 curproxy->options2 &= ~PR_O2_CHK_ANY;
5113 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005114 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5115 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005116 }
Simon Horman98637e52014-06-20 12:30:16 +09005117 else if (!strcmp(args[1], "external-check")) {
5118 /* excute an external command to check servers' health */
5119 free(curproxy->check_req);
5120 curproxy->check_req = NULL;
5121 curproxy->options2 &= ~PR_O2_CHK_ANY;
5122 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005123 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5124 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005125 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005126 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005127 int cur_arg;
5128
5129 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5130 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005131 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005132
Willy Tarreau87cf5142011-08-19 22:57:24 +02005133 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005134
5135 free(curproxy->fwdfor_hdr_name);
5136 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5137 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5138
5139 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5140 cur_arg = 2;
5141 while (*(args[cur_arg])) {
5142 if (!strcmp(args[cur_arg], "except")) {
5143 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005144 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005145 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5146 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005149 }
5150 /* flush useless bits */
5151 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005152 cur_arg += 2;
5153 } else if (!strcmp(args[cur_arg], "header")) {
5154 /* suboption header - needs additional argument for it */
5155 if (*(args[cur_arg+1]) == 0) {
5156 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5157 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005160 }
5161 free(curproxy->fwdfor_hdr_name);
5162 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5163 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5164 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005165 } else if (!strcmp(args[cur_arg], "if-none")) {
5166 curproxy->options &= ~PR_O_FF_ALWAYS;
5167 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005168 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005169 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005170 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005171 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005174 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005175 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005176 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005177 else if (!strcmp(args[1], "originalto")) {
5178 int cur_arg;
5179
5180 /* insert x-original-to field, but not for the IP address listed as an except.
5181 * set default options (ie: bitfield, header name, etc)
5182 */
5183
5184 curproxy->options |= PR_O_ORGTO;
5185
5186 free(curproxy->orgto_hdr_name);
5187 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5188 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5189
Willy Tarreau87cf5142011-08-19 22:57:24 +02005190 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005191 cur_arg = 2;
5192 while (*(args[cur_arg])) {
5193 if (!strcmp(args[cur_arg], "except")) {
5194 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005195 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 +02005196 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5197 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005200 }
5201 /* flush useless bits */
5202 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5203 cur_arg += 2;
5204 } else if (!strcmp(args[cur_arg], "header")) {
5205 /* suboption header - needs additional argument for it */
5206 if (*(args[cur_arg+1]) == 0) {
5207 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5208 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005211 }
5212 free(curproxy->orgto_hdr_name);
5213 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5214 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5215 cur_arg += 2;
5216 } else {
5217 /* unknown suboption - catchall */
5218 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5219 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005222 }
5223 } /* end while loop */
5224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 else {
5226 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreau93893792009-07-23 13:19:11 +02005230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005232 else if (!strcmp(args[0], "default_backend")) {
5233 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005234 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005235
5236 if (*(args[1]) == 0) {
5237 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005240 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005241 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005242 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005243
5244 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5245 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005250
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005251 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5252 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 +01005253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005254 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 /* enable reconnections to dispatch */
5256 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005257
5258 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005261 else if (!strcmp(args[0], "http-reuse")) {
5262 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5263 err_code |= ERR_WARN;
5264
5265 if (strcmp(args[1], "never") == 0) {
5266 /* enable a graceful server shutdown on an HTTP 404 response */
5267 curproxy->options &= ~PR_O_REUSE_MASK;
5268 curproxy->options |= PR_O_REUSE_NEVR;
5269 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5270 goto out;
5271 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005272 else if (strcmp(args[1], "safe") == 0) {
5273 /* enable a graceful server shutdown on an HTTP 404 response */
5274 curproxy->options &= ~PR_O_REUSE_MASK;
5275 curproxy->options |= PR_O_REUSE_SAFE;
5276 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5277 goto out;
5278 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005279 else if (strcmp(args[1], "aggressive") == 0) {
5280 curproxy->options &= ~PR_O_REUSE_MASK;
5281 curproxy->options |= PR_O_REUSE_AGGR;
5282 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5283 goto out;
5284 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005285 else if (strcmp(args[1], "always") == 0) {
5286 /* enable a graceful server shutdown on an HTTP 404 response */
5287 curproxy->options &= ~PR_O_REUSE_MASK;
5288 curproxy->options |= PR_O_REUSE_ALWS;
5289 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5290 goto out;
5291 }
5292 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005293 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005298 else if (!strcmp(args[0], "http-check")) {
5299 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005301
5302 if (strcmp(args[1], "disable-on-404") == 0) {
5303 /* enable a graceful server shutdown on an HTTP 404 response */
5304 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005305 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5306 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005307 }
Willy Tarreauef781042010-01-27 11:53:01 +01005308 else if (strcmp(args[1], "send-state") == 0) {
5309 /* enable emission of the apparent state of a server in HTTP checks */
5310 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005311 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5312 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005313 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005314 else if (strcmp(args[1], "expect") == 0) {
5315 const char *ptr_arg;
5316 int cur_arg;
5317
5318 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5319 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
5323
5324 cur_arg = 2;
5325 /* consider exclamation marks, sole or at the beginning of a word */
5326 while (*(ptr_arg = args[cur_arg])) {
5327 while (*ptr_arg == '!') {
5328 curproxy->options2 ^= PR_O2_EXP_INV;
5329 ptr_arg++;
5330 }
5331 if (*ptr_arg)
5332 break;
5333 cur_arg++;
5334 }
5335 /* now ptr_arg points to the beginning of a word past any possible
5336 * exclamation mark, and cur_arg is the argument which holds this word.
5337 */
5338 if (strcmp(ptr_arg, "status") == 0) {
5339 if (!*(args[cur_arg + 1])) {
5340 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5341 file, linenum, args[0], args[1], ptr_arg);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005346 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005347 curproxy->expect_str = strdup(args[cur_arg + 1]);
5348 }
5349 else if (strcmp(ptr_arg, "string") == 0) {
5350 if (!*(args[cur_arg + 1])) {
5351 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5352 file, linenum, args[0], args[1], ptr_arg);
5353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005357 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005358 curproxy->expect_str = strdup(args[cur_arg + 1]);
5359 }
5360 else if (strcmp(ptr_arg, "rstatus") == 0) {
5361 if (!*(args[cur_arg + 1])) {
5362 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5363 file, linenum, args[0], args[1], ptr_arg);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005368 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005369 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005370 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005371 free(curproxy->expect_regex);
5372 curproxy->expect_regex = NULL;
5373 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005374 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005375 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5376 error = NULL;
5377 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5378 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5379 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5380 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 }
5385 else if (strcmp(ptr_arg, "rstring") == 0) {
5386 if (!*(args[cur_arg + 1])) {
5387 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5388 file, linenum, args[0], args[1], ptr_arg);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
5392 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005393 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005394 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005395 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005396 free(curproxy->expect_regex);
5397 curproxy->expect_regex = NULL;
5398 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005399 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005400 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5401 error = NULL;
5402 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5403 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5404 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5405 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409 }
5410 else {
5411 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5412 file, linenum, args[0], args[1], ptr_arg);
5413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
5415 }
5416 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005417 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005418 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 +02005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005421 }
5422 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005423 else if (!strcmp(args[0], "tcp-check")) {
5424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5425 err_code |= ERR_WARN;
5426
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005427 if (strcmp(args[1], "comment") == 0) {
5428 int cur_arg;
5429 struct tcpcheck_rule *tcpcheck;
5430
5431 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005432 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005433 tcpcheck->action = TCPCHK_ACT_COMMENT;
5434
5435 if (!*args[cur_arg + 1]) {
5436 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5437 file, linenum, args[cur_arg]);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441
5442 tcpcheck->comment = strdup(args[cur_arg + 1]);
5443
5444 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005445 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5446 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005447 }
5448 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005449 const char *ptr_arg;
5450 int cur_arg;
5451 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005452
5453 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005454 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5455 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5456 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5457 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5458 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005459
Willy Tarreau5581c272015-05-13 12:24:53 +02005460 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5461 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5462 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5463 file, linenum);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005466 }
5467
5468 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005469 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005470 tcpcheck->action = TCPCHK_ACT_CONNECT;
5471
5472 /* parsing each parameters to fill up the rule */
5473 while (*(ptr_arg = args[cur_arg])) {
5474 /* tcp port */
5475 if (strcmp(args[cur_arg], "port") == 0) {
5476 if ( (atol(args[cur_arg + 1]) > 65535) ||
5477 (atol(args[cur_arg + 1]) < 1) ){
5478 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5479 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 }
5483 tcpcheck->port = atol(args[cur_arg + 1]);
5484 cur_arg += 2;
5485 }
5486 /* send proxy protocol */
5487 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5488 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5489 cur_arg++;
5490 }
5491#ifdef USE_OPENSSL
5492 else if (strcmp(args[cur_arg], "ssl") == 0) {
5493 curproxy->options |= PR_O_TCPCHK_SSL;
5494 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5495 cur_arg++;
5496 }
5497#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005498 /* comment for this tcpcheck line */
5499 else if (strcmp(args[cur_arg], "comment") == 0) {
5500 if (!*args[cur_arg + 1]) {
5501 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5502 file, linenum, args[cur_arg]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 tcpcheck->comment = strdup(args[cur_arg + 1]);
5507 cur_arg += 2;
5508 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005509 else {
5510#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005511 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 +01005512#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005513 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 +01005514#endif /* USE_OPENSSL */
5515 file, linenum, args[0], args[1], args[cur_arg]);
5516 err_code |= ERR_ALERT | ERR_FATAL;
5517 goto out;
5518 }
5519
5520 }
5521
5522 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5523 }
5524 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005525 if (! *(args[2]) ) {
5526 /* SEND string expected */
5527 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5528 file, linenum, args[0], args[1], args[2]);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 } else {
5532 struct tcpcheck_rule *tcpcheck;
5533
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005534 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005535
5536 tcpcheck->action = TCPCHK_ACT_SEND;
5537 tcpcheck->string_len = strlen(args[2]);
5538 tcpcheck->string = strdup(args[2]);
5539 tcpcheck->expect_regex = NULL;
5540
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005541 /* comment for this tcpcheck line */
5542 if (strcmp(args[3], "comment") == 0) {
5543 if (!*args[4]) {
5544 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5545 file, linenum, args[3]);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
5549 tcpcheck->comment = strdup(args[4]);
5550 }
5551
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005552 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5553 }
5554 }
5555 else if (strcmp(args[1], "send-binary") == 0) {
5556 if (! *(args[2]) ) {
5557 /* SEND binary string expected */
5558 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5559 file, linenum, args[0], args[1], args[2]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 } else {
5563 struct tcpcheck_rule *tcpcheck;
5564 char *err = NULL;
5565
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005566 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005567
5568 tcpcheck->action = TCPCHK_ACT_SEND;
5569 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5570 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5571 file, linenum, args[0], args[1], args[2], err);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575 tcpcheck->expect_regex = NULL;
5576
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005577 /* comment for this tcpcheck line */
5578 if (strcmp(args[3], "comment") == 0) {
5579 if (!*args[4]) {
5580 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5581 file, linenum, args[3]);
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
5584 }
5585 tcpcheck->comment = strdup(args[4]);
5586 }
5587
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005588 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5589 }
5590 }
5591 else if (strcmp(args[1], "expect") == 0) {
5592 const char *ptr_arg;
5593 int cur_arg;
5594 int inverse = 0;
5595
5596 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5597 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
5600 }
5601
5602 cur_arg = 2;
5603 /* consider exclamation marks, sole or at the beginning of a word */
5604 while (*(ptr_arg = args[cur_arg])) {
5605 while (*ptr_arg == '!') {
5606 inverse = !inverse;
5607 ptr_arg++;
5608 }
5609 if (*ptr_arg)
5610 break;
5611 cur_arg++;
5612 }
5613 /* now ptr_arg points to the beginning of a word past any possible
5614 * exclamation mark, and cur_arg is the argument which holds this word.
5615 */
5616 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005617 struct tcpcheck_rule *tcpcheck;
5618 char *err = NULL;
5619
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005620 if (!*(args[cur_arg + 1])) {
5621 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5622 file, linenum, args[0], args[1], ptr_arg);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005626
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005627 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005628
5629 tcpcheck->action = TCPCHK_ACT_EXPECT;
5630 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5631 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5632 file, linenum, args[0], args[1], args[2], err);
5633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
5636 tcpcheck->expect_regex = NULL;
5637 tcpcheck->inverse = inverse;
5638
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005639 /* tcpcheck comment */
5640 cur_arg += 2;
5641 if (strcmp(args[cur_arg], "comment") == 0) {
5642 if (!*args[cur_arg + 1]) {
5643 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5644 file, linenum, args[cur_arg + 1]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648 tcpcheck->comment = strdup(args[cur_arg + 1]);
5649 }
5650
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5652 }
5653 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005654 struct tcpcheck_rule *tcpcheck;
5655
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005656 if (!*(args[cur_arg + 1])) {
5657 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5658 file, linenum, args[0], args[1], ptr_arg);
5659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005662
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005663 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005664
5665 tcpcheck->action = TCPCHK_ACT_EXPECT;
5666 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5667 tcpcheck->string = strdup(args[cur_arg + 1]);
5668 tcpcheck->expect_regex = NULL;
5669 tcpcheck->inverse = inverse;
5670
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005671 /* tcpcheck comment */
5672 cur_arg += 2;
5673 if (strcmp(args[cur_arg], "comment") == 0) {
5674 if (!*args[cur_arg + 1]) {
5675 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5676 file, linenum, args[cur_arg + 1]);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
5680 tcpcheck->comment = strdup(args[cur_arg + 1]);
5681 }
5682
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005683 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5684 }
5685 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005686 struct tcpcheck_rule *tcpcheck;
5687
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005688 if (!*(args[cur_arg + 1])) {
5689 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5690 file, linenum, args[0], args[1], ptr_arg);
5691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005694
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005695 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005696
5697 tcpcheck->action = TCPCHK_ACT_EXPECT;
5698 tcpcheck->string_len = 0;
5699 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005700 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5701 error = NULL;
5702 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5703 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5704 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5705 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
5708 }
5709 tcpcheck->inverse = inverse;
5710
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005711 /* tcpcheck comment */
5712 cur_arg += 2;
5713 if (strcmp(args[cur_arg], "comment") == 0) {
5714 if (!*args[cur_arg + 1]) {
5715 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5716 file, linenum, args[cur_arg + 1]);
5717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
5720 tcpcheck->comment = strdup(args[cur_arg + 1]);
5721 }
5722
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005723 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5724 }
5725 else {
5726 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5727 file, linenum, args[0], args[1], ptr_arg);
5728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
5730 }
5731 }
5732 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005733 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
5737 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005738 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005739 if (curproxy == &defproxy) {
5740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005743 }
5744
Willy Tarreaub80c2302007-11-30 20:51:32 +01005745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005747
5748 if (strcmp(args[1], "fail") == 0) {
5749 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005750 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005751 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5752 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005755 }
5756
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005757 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5758 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5759 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005762 }
5763 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5764 }
5765 else {
5766 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005769 }
5770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771#ifdef TPROXY
5772 else if (!strcmp(args[0], "transparent")) {
5773 /* enable transparent proxy connections */
5774 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005775 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
5778#endif
5779 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005782
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 if (*(args[1]) == 0) {
5784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
5788 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005789 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005792 else if (!strcmp(args[0], "backlog")) { /* backlog */
5793 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005795
5796 if (*(args[1]) == 0) {
5797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005800 }
5801 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005802 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5803 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005804 }
Willy Tarreau86034312006-12-29 00:10:33 +01005805 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005806 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005807 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005808
Willy Tarreau86034312006-12-29 00:10:33 +01005809 if (*(args[1]) == 0) {
5810 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005813 }
5814 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005815 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5816 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5819 if (*(args[1]) == 0) {
5820 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005824 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5825 if (err) {
5826 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5827 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005830 }
5831 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005832 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
5835 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005836 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005837 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005838 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005839
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 if (curproxy == &defproxy) {
5841 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005845 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005847
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005848 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005849 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005850 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005851 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005852 goto out;
5853 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005854
5855 proto = protocol_by_family(sk->ss_family);
5856 if (!proto || !proto->connect) {
5857 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5858 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861 }
5862
5863 if (port1 != port2) {
5864 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5865 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005869
5870 if (!port1) {
5871 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5872 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005876
William Lallemanddf1425a2015-04-28 20:17:49 +02005877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5878 goto out;
5879
Willy Tarreaud5191e72010-02-09 20:50:45 +01005880 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005881 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 }
5883 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005884 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005886
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005887 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5888 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005893 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005894 /**
5895 * The syntax for hash-type config element is
5896 * hash-type {map-based|consistent} [[<algo>] avalanche]
5897 *
5898 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5899 */
5900 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005901
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5903 err_code |= ERR_WARN;
5904
5905 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005906 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5907 }
5908 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005909 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5910 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005911 else if (strcmp(args[1], "avalanche") == 0) {
5912 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]);
5913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005915 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005916 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005917 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
5920 }
Bhaskar98634f02013-10-29 23:30:51 -04005921
5922 /* set the hash function to use */
5923 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005924 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005925 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005926
5927 /* if consistent with no argument, then avalanche modifier is also applied */
5928 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5929 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005930 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005931 /* set the hash function */
5932 if (!strcmp(args[2], "sdbm")) {
5933 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5934 }
5935 else if (!strcmp(args[2], "djb2")) {
5936 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005937 }
5938 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005939 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005940 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005941 else if (!strcmp(args[2], "crc32")) {
5942 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5943 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005944 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005945 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 -05005946 err_code |= ERR_ALERT | ERR_FATAL;
5947 goto out;
5948 }
5949
5950 /* set the hash modifier */
5951 if (!strcmp(args[3], "avalanche")) {
5952 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5953 }
5954 else if (*args[3]) {
5955 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005959 }
William Lallemanda73203e2012-03-12 12:48:57 +01005960 }
William Lallemanda73203e2012-03-12 12:48:57 +01005961 else if (strcmp(args[0], "unique-id-format") == 0) {
5962 if (!*(args[1])) {
5963 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
William Lallemand3203ff42012-11-11 17:30:56 +01005967 if (*(args[2])) {
5968 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005972 free(curproxy->conf.uniqueid_format_string);
5973 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005974
Willy Tarreau62a61232013-04-12 18:13:46 +02005975 free(curproxy->conf.uif_file);
5976 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5977 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005978 }
William Lallemanda73203e2012-03-12 12:48:57 +01005979
5980 else if (strcmp(args[0], "unique-id-header") == 0) {
5981 if (!*(args[1])) {
5982 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
5986 free(curproxy->header_unique_id);
5987 curproxy->header_unique_id = strdup(args[1]);
5988 }
5989
William Lallemand723b73a2012-02-08 16:37:49 +01005990 else if (strcmp(args[0], "log-format") == 0) {
5991 if (!*(args[1])) {
5992 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
William Lallemand3203ff42012-11-11 17:30:56 +01005996 if (*(args[2])) {
5997 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006001
Willy Tarreau62a61232013-04-12 18:13:46 +02006002 if (curproxy->conf.logformat_string != default_http_log_format &&
6003 curproxy->conf.logformat_string != default_tcp_log_format &&
6004 curproxy->conf.logformat_string != clf_http_log_format)
6005 free(curproxy->conf.logformat_string);
6006 curproxy->conf.logformat_string = strdup(args[1]);
6007
6008 free(curproxy->conf.lfs_file);
6009 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6010 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006011
6012 /* get a chance to improve log-format error reporting by
6013 * reporting the correct line-number when possible.
6014 */
6015 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6016 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6017 file, linenum, curproxy->id);
6018 err_code |= ERR_WARN;
6019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006021 else if (!strcmp(args[0], "log-format-sd")) {
6022 if (!*(args[1])) {
6023 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
6026 }
6027 if (*(args[2])) {
6028 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
6032
6033 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6034 free(curproxy->conf.logformat_sd_string);
6035 curproxy->conf.logformat_sd_string = strdup(args[1]);
6036
6037 free(curproxy->conf.lfsd_file);
6038 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6039 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6040
6041 /* get a chance to improve log-format-sd error reporting by
6042 * reporting the correct line-number when possible.
6043 */
6044 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6045 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6046 file, linenum, curproxy->id);
6047 err_code |= ERR_WARN;
6048 }
6049 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006050 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6051 if (*(args[1]) == 0) {
6052 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006056 chunk_destroy(&curproxy->log_tag);
6057 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006058 }
William Lallemand0f99e342011-10-12 17:50:54 +02006059 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6060 /* delete previous herited or defined syslog servers */
6061 struct logsrv *back;
6062
6063 if (*(args[1]) != 0) {
6064 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067 }
6068
William Lallemand723b73a2012-02-08 16:37:49 +01006069 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6070 LIST_DEL(&tmplogsrv->list);
6071 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006072 }
6073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006074 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006075 struct logsrv *logsrv;
6076
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006078 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006079 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006080 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006081 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006082 LIST_INIT(&node->list);
6083 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006085 }
6086 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006087 struct sockaddr_storage *sk;
6088 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006089 int arg = 0;
6090 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006091
Vincent Bernat02779b62016-04-03 13:48:43 +02006092 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093
Willy Tarreau18324f52014-06-27 18:10:07 +02006094 /* just after the address, a length may be specified */
6095 if (strcmp(args[arg+2], "len") == 0) {
6096 len = atoi(args[arg+3]);
6097 if (len < 80 || len > 65535) {
6098 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6099 file, linenum, args[arg+3]);
6100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
6102 }
6103 logsrv->maxlen = len;
6104
6105 /* skip these two args */
6106 arg += 2;
6107 }
6108 else
6109 logsrv->maxlen = MAX_SYSLOG_LEN;
6110
6111 if (logsrv->maxlen > global.max_syslog_len) {
6112 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006113 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6114 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6115 logline = my_realloc2(logline, global.max_syslog_len + 1);
6116 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006117 }
6118
Dragan Dosen1322d092015-09-22 16:05:32 +02006119 /* after the length, a format may be specified */
6120 if (strcmp(args[arg+2], "format") == 0) {
6121 logsrv->format = get_log_format(args[arg+3]);
6122 if (logsrv->format < 0) {
6123 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6124 err_code |= ERR_ALERT | ERR_FATAL;
6125 goto out;
6126 }
6127
6128 /* skip these two args */
6129 arg += 2;
6130 }
6131
William Lallemanddf1425a2015-04-28 20:17:49 +02006132 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6133 goto out;
6134
Willy Tarreau18324f52014-06-27 18:10:07 +02006135 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006136 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006137 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 }
6142
William Lallemand0f99e342011-10-12 17:50:54 +02006143 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006144 if (*(args[arg+3])) {
6145 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006146 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006147 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
6150
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 }
6152 }
6153
William Lallemand0f99e342011-10-12 17:50:54 +02006154 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006155 if (*(args[arg+4])) {
6156 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006157 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006158 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
6161
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006162 }
6163 }
6164
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006165 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006166 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006167 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006168 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006169 goto out;
6170 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006171
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006172 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006173
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006174 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006175 if (port1 != port2) {
6176 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6177 file, linenum, args[0], args[1]);
6178 err_code |= ERR_ALERT | ERR_FATAL;
6179 goto out;
6180 }
6181
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006182 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006183 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 }
William Lallemand0f99e342011-10-12 17:50:54 +02006185
6186 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006187 }
6188 else {
6189 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6190 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006191 err_code |= ERR_ALERT | ERR_FATAL;
6192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 }
6194 }
6195 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006196 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006197 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006198 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006199 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006200
Willy Tarreau977b8e42006-12-29 14:19:17 +01006201 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006203
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006205 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6206 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006210
6211 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006212 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6213 free(curproxy->conn_src.iface_name);
6214 curproxy->conn_src.iface_name = NULL;
6215 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006216
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006217 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006218 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006219 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006220 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006221 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006222 goto out;
6223 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006224
6225 proto = protocol_by_family(sk->ss_family);
6226 if (!proto || !proto->connect) {
6227 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006228 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006229 err_code |= ERR_ALERT | ERR_FATAL;
6230 goto out;
6231 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006232
6233 if (port1 != port2) {
6234 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6235 file, linenum, args[0], args[1]);
6236 err_code |= ERR_ALERT | ERR_FATAL;
6237 goto out;
6238 }
6239
Willy Tarreauef9a3602012-12-08 22:29:20 +01006240 curproxy->conn_src.source_addr = *sk;
6241 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006242
6243 cur_arg = 2;
6244 while (*(args[cur_arg])) {
6245 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006246#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006247 if (!*args[cur_arg + 1]) {
6248 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6249 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006250 err_code |= ERR_ALERT | ERR_FATAL;
6251 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006252 }
6253
6254 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006255 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6256 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006257 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006258 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6259 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006260 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6261 char *name, *end;
6262
6263 name = args[cur_arg+1] + 7;
6264 while (isspace(*name))
6265 name++;
6266
6267 end = name;
6268 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6269 end++;
6270
Willy Tarreauef9a3602012-12-08 22:29:20 +01006271 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6272 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6273 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6274 curproxy->conn_src.bind_hdr_len = end - name;
6275 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6276 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6277 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006278
6279 /* now look for an occurrence number */
6280 while (isspace(*end))
6281 end++;
6282 if (*end == ',') {
6283 end++;
6284 name = end;
6285 if (*end == '-')
6286 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006287 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006288 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006289 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006290 }
6291
Willy Tarreauef9a3602012-12-08 22:29:20 +01006292 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006293 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6294 " occurrences values smaller than %d.\n",
6295 file, linenum, MAX_HDR_HISTORY);
6296 err_code |= ERR_ALERT | ERR_FATAL;
6297 goto out;
6298 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006300 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006301
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006302 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006303 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006304 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006305 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006306 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006307 goto out;
6308 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006309
6310 proto = protocol_by_family(sk->ss_family);
6311 if (!proto || !proto->connect) {
6312 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6313 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
6316 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006317
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006318 if (port1 != port2) {
6319 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6320 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
6323 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006324 curproxy->conn_src.tproxy_addr = *sk;
6325 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006326 }
6327 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006328#else /* no TPROXY support */
6329 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006330 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006331 err_code |= ERR_ALERT | ERR_FATAL;
6332 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006333#endif
6334 cur_arg += 2;
6335 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006336 }
6337
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006338 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6339#ifdef SO_BINDTODEVICE
6340 if (!*args[cur_arg + 1]) {
6341 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006343 err_code |= ERR_ALERT | ERR_FATAL;
6344 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006345 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006346 free(curproxy->conn_src.iface_name);
6347 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6348 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006349 global.last_checks |= LSTCHK_NETADM;
6350#else
6351 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6352 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006353 err_code |= ERR_ALERT | ERR_FATAL;
6354 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006355#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006356 cur_arg += 2;
6357 continue;
6358 }
6359 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006360 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006361 err_code |= ERR_ALERT | ERR_FATAL;
6362 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006365 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6366 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6367 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006368 err_code |= ERR_ALERT | ERR_FATAL;
6369 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006375 err_code |= ERR_ALERT | ERR_FATAL;
6376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378
6379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006380 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006381 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 }
6385 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006387 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006388 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 }
6392 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006394 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006395 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
6399 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006401 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006402 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
6406 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006408 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006409 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006413 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006415 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006418 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427
6428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006430 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
6434 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
6441 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006442 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006443 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006444 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006445 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
6448 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006449 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006450 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006451 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006452 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
6455 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006457 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006458 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006462 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006464 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006465 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006467 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006470 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006471
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 if (curproxy == &defproxy) {
6473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006474 err_code |= ERR_ALERT | ERR_FATAL;
6475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006477 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006478 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 if (*(args[1]) == 0) {
6481 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006485
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006486 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006487 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6488 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6489 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006490 err_code |= ERR_ALERT | ERR_FATAL;
6491 goto out;
6492 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006493 err_code |= warnif_cond_conflicts(cond,
6494 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6495 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006496 }
6497 else if (*args[2]) {
6498 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6499 file, linenum, args[0], args[2]);
6500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto out;
6502 }
6503
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006504 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006505 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006506 wl->s = strdup(args[1]);
6507 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006508 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006514 err_code |= ERR_ALERT | ERR_FATAL;
6515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006517
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006519 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006520 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006526 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006527 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
6531 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006533 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
6538 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006539 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6541 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006542 err_code |= ERR_ALERT | ERR_FATAL;
6543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 }
6545
Willy Tarreauade5ec42010-01-28 19:33:49 +01006546 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006547 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006548 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006549 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 }
6552 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006553 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006554 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006556 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558 }
6559 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006561 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006562 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 }
6566 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006567 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006568
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569 if (curproxy == &defproxy) {
6570 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", 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 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006575 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 if (*(args[1]) == 0) {
6578 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006579 err_code |= ERR_ALERT | ERR_FATAL;
6580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
6582
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006583 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006584 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6585 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6586 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006587 err_code |= ERR_ALERT | ERR_FATAL;
6588 goto out;
6589 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006590 err_code |= warnif_cond_conflicts(cond,
6591 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6592 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006593 }
6594 else if (*args[2]) {
6595 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6596 file, linenum, args[0], args[2]);
6597 err_code |= ERR_ALERT | ERR_FATAL;
6598 goto out;
6599 }
6600
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006601 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006602 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006603 wl->s = strdup(args[1]);
6604 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 }
6606 else if (!strcmp(args[0], "errorloc") ||
6607 !strcmp(args[0], "errorloc302") ||
6608 !strcmp(args[0], "errorloc303")) { /* error location */
6609 int errnum, errlen;
6610 char *err;
6611
Willy Tarreau977b8e42006-12-29 14:19:17 +01006612 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006613 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006614
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006616 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006617 err_code |= ERR_ALERT | ERR_FATAL;
6618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006619 }
6620
6621 errnum = atol(args[1]);
6622 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006623 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6624 err = malloc(errlen);
6625 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006626 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006627 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6628 err = malloc(errlen);
6629 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006630 }
6631
Willy Tarreau0f772532006-12-23 20:51:41 +01006632 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6633 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006634 chunk_destroy(&curproxy->errmsg[rc]);
6635 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006636 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006638 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006639
6640 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006641 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6642 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006643 free(err);
6644 }
6645 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006646 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6647 int errnum, errlen, fd;
6648 char *err;
6649 struct stat stat;
6650
6651 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006652 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006653
6654 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006655 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006656 err_code |= ERR_ALERT | ERR_FATAL;
6657 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006658 }
6659
6660 fd = open(args[2], O_RDONLY);
6661 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6662 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6663 file, linenum, args[2], args[1]);
6664 if (fd >= 0)
6665 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006666 err_code |= ERR_ALERT | ERR_FATAL;
6667 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006668 }
6669
Willy Tarreau27a674e2009-08-17 07:23:33 +02006670 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006671 errlen = stat.st_size;
6672 } else {
6673 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006674 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006675 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006676 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006677 }
6678
6679 err = malloc(errlen); /* malloc() must succeed during parsing */
6680 errnum = read(fd, err, errlen);
6681 if (errnum != errlen) {
6682 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6683 file, linenum, args[2], args[1]);
6684 close(fd);
6685 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006686 err_code |= ERR_ALERT | ERR_FATAL;
6687 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006688 }
6689 close(fd);
6690
6691 errnum = atol(args[1]);
6692 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6693 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006694 chunk_destroy(&curproxy->errmsg[rc]);
6695 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006696 break;
6697 }
6698 }
6699
6700 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006701 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6702 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006703 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006704 free(err);
6705 }
6706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006707 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006708 struct cfg_kw_list *kwl;
6709 int index;
6710
6711 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6712 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6713 if (kwl->kw[index].section != CFG_LISTEN)
6714 continue;
6715 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6716 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006717 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006718 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006719 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006720 err_code |= ERR_ALERT | ERR_FATAL;
6721 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006722 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006723 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006724 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006725 err_code |= ERR_WARN;
6726 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006727 }
Willy Tarreau93893792009-07-23 13:19:11 +02006728 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006729 }
6730 }
6731 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006732
Willy Tarreau6daf3432008-01-22 16:44:08 +01006733 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006734 err_code |= ERR_ALERT | ERR_FATAL;
6735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006736 }
Willy Tarreau93893792009-07-23 13:19:11 +02006737 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006738 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006739 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006740}
6741
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006743cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6744{
6745#ifdef CONFIG_HAP_NS
6746 const char *err;
6747 const char *item = args[0];
6748
6749 if (!strcmp(item, "namespace_list")) {
6750 return 0;
6751 }
6752 else if (!strcmp(item, "namespace")) {
6753 size_t idx = 1;
6754 const char *current;
6755 while (*(current = args[idx++])) {
6756 err = invalid_char(current);
6757 if (err) {
6758 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6759 file, linenum, *err, item, current);
6760 return ERR_ALERT | ERR_FATAL;
6761 }
6762
6763 if (netns_store_lookup(current, strlen(current))) {
6764 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6765 file, linenum, current);
6766 return ERR_ALERT | ERR_FATAL;
6767 }
6768 if (!netns_store_insert(current)) {
6769 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6770 file, linenum, current);
6771 return ERR_ALERT | ERR_FATAL;
6772 }
6773 }
6774 }
6775
6776 return 0;
6777#else
6778 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6779 file, linenum);
6780 return ERR_ALERT | ERR_FATAL;
6781#endif
6782}
6783
6784int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006785cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6786{
6787
6788 int err_code = 0;
6789 const char *err;
6790
6791 if (!strcmp(args[0], "userlist")) { /* new userlist */
6792 struct userlist *newul;
6793
6794 if (!*args[1]) {
6795 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6796 file, linenum, args[0]);
6797 err_code |= ERR_ALERT | ERR_FATAL;
6798 goto out;
6799 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006800 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6801 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802
6803 err = invalid_char(args[1]);
6804 if (err) {
6805 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6806 file, linenum, *err, args[0], args[1]);
6807 err_code |= ERR_ALERT | ERR_FATAL;
6808 goto out;
6809 }
6810
6811 for (newul = userlist; newul; newul = newul->next)
6812 if (!strcmp(newul->name, args[1])) {
6813 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6814 file, linenum, args[1]);
6815 err_code |= ERR_WARN;
6816 goto out;
6817 }
6818
Vincent Bernat02779b62016-04-03 13:48:43 +02006819 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006820 if (!newul) {
6821 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6822 err_code |= ERR_ALERT | ERR_ABORT;
6823 goto out;
6824 }
6825
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006826 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006827 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006828 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6829 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006830 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006831 goto out;
6832 }
6833
6834 newul->next = userlist;
6835 userlist = newul;
6836
6837 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006838 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006839 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006840 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006841
6842 if (!*args[1]) {
6843 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6844 file, linenum, args[0]);
6845 err_code |= ERR_ALERT | ERR_FATAL;
6846 goto out;
6847 }
6848
6849 err = invalid_char(args[1]);
6850 if (err) {
6851 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6852 file, linenum, *err, args[0], args[1]);
6853 err_code |= ERR_ALERT | ERR_FATAL;
6854 goto out;
6855 }
6856
William Lallemand4ac9f542015-05-28 18:03:51 +02006857 if (!userlist)
6858 goto out;
6859
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006860 for (ag = userlist->groups; ag; ag = ag->next)
6861 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6863 file, linenum, args[1], userlist->name);
6864 err_code |= ERR_ALERT;
6865 goto out;
6866 }
6867
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006868 ag = calloc(1, sizeof(*ag));
6869 if (!ag) {
6870 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6871 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 goto out;
6873 }
6874
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006875 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006876 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006877 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6878 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006879 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006880 goto out;
6881 }
6882
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006883 cur_arg = 2;
6884
6885 while (*args[cur_arg]) {
6886 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006887 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888 cur_arg += 2;
6889 continue;
6890 } else {
6891 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6892 file, linenum, args[0]);
6893 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006894 free(ag->groupusers);
6895 free(ag->name);
6896 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006897 goto out;
6898 }
6899 }
6900
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006901 ag->next = userlist->groups;
6902 userlist->groups = ag;
6903
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006904 } else if (!strcmp(args[0], "user")) { /* new user */
6905 struct auth_users *newuser;
6906 int cur_arg;
6907
6908 if (!*args[1]) {
6909 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6910 file, linenum, args[0]);
6911 err_code |= ERR_ALERT | ERR_FATAL;
6912 goto out;
6913 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006914 if (!userlist)
6915 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006916
6917 for (newuser = userlist->users; newuser; newuser = newuser->next)
6918 if (!strcmp(newuser->user, args[1])) {
6919 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6920 file, linenum, args[1], userlist->name);
6921 err_code |= ERR_ALERT;
6922 goto out;
6923 }
6924
Vincent Bernat02779b62016-04-03 13:48:43 +02006925 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006926 if (!newuser) {
6927 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6928 err_code |= ERR_ALERT | ERR_ABORT;
6929 goto out;
6930 }
6931
6932 newuser->user = strdup(args[1]);
6933
6934 newuser->next = userlist->users;
6935 userlist->users = newuser;
6936
6937 cur_arg = 2;
6938
6939 while (*args[cur_arg]) {
6940 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006941#ifdef CONFIG_HAP_CRYPT
6942 if (!crypt("", args[cur_arg + 1])) {
6943 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6944 file, linenum, newuser->user);
6945 err_code |= ERR_ALERT | ERR_FATAL;
6946 goto out;
6947 }
6948#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006949 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6950 file, linenum);
6951 err_code |= ERR_ALERT;
6952#endif
6953 newuser->pass = strdup(args[cur_arg + 1]);
6954 cur_arg += 2;
6955 continue;
6956 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6957 newuser->pass = strdup(args[cur_arg + 1]);
6958 newuser->flags |= AU_O_INSECURE;
6959 cur_arg += 2;
6960 continue;
6961 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006962 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006963 cur_arg += 2;
6964 continue;
6965 } else {
6966 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6967 file, linenum, args[0]);
6968 err_code |= ERR_ALERT | ERR_FATAL;
6969 goto out;
6970 }
6971 }
6972 } else {
6973 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6974 err_code |= ERR_ALERT | ERR_FATAL;
6975 }
6976
6977out:
6978 return err_code;
6979}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006980
6981/*
6982 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006983 * Returns the error code, 0 if OK, or any combination of :
6984 * - ERR_ABORT: must abort ASAP
6985 * - ERR_FATAL: we can continue parsing but not start the service
6986 * - ERR_WARN: a warning has been emitted
6987 * - ERR_ALERT: an alert has been emitted
6988 * Only the two first ones can stop processing, the two others are just
6989 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006991int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992{
William Lallemand64e84512015-05-12 14:25:37 +02006993 char *thisline;
6994 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 FILE *f;
6996 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006997 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006998 struct cfg_section *cs = NULL;
6999 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007000 int readbytes = 0;
7001
7002 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007003 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007004 return -1;
7005 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007006
David Carlier97880bb2016-04-08 10:35:26 +01007007 if ((f=fopen(file,"r")) == NULL) {
7008 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007009 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011
William Lallemandb2f07452015-05-12 14:27:13 +02007012next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007013 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007014 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007015 char *end;
7016 char *args[MAX_LINE_ARGS + 1];
7017 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007018 int dquote = 0; /* double quote */
7019 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007020
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021 linenum++;
7022
7023 end = line + strlen(line);
7024
William Lallemand64e84512015-05-12 14:25:37 +02007025 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007026 /* Check if we reached the limit and the last char is not \n.
7027 * Watch out for the last line without the terminating '\n'!
7028 */
William Lallemand64e84512015-05-12 14:25:37 +02007029 char *newline;
7030 int newlinesize = linesize * 2;
7031
7032 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7033 if (newline == NULL) {
7034 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7035 file, linenum);
7036 err_code |= ERR_ALERT | ERR_FATAL;
7037 continue;
7038 }
7039
7040 readbytes = linesize - 1;
7041 linesize = newlinesize;
7042 thisline = newline;
7043 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007044 }
7045
William Lallemand64e84512015-05-12 14:25:37 +02007046 readbytes = 0;
7047
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007049 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007050 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007051
Willy Tarreaubaaee002006-06-26 02:48:02 +02007052 arg = 0;
7053 args[arg] = line;
7054
7055 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007056 if (*line == '"' && !squote) { /* double quote outside single quotes */
7057 if (dquote)
7058 dquote = 0;
7059 else
7060 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007061 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007062 end--;
7063 }
7064 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7065 if (squote)
7066 squote = 0;
7067 else
7068 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007069 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007070 end--;
7071 }
7072 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007073 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7074 * C equivalent value. Other combinations left unchanged (eg: \1).
7075 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007076 int skip = 0;
7077 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7078 *line = line[1];
7079 skip = 1;
7080 }
7081 else if (line[1] == 'r') {
7082 *line = '\r';
7083 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 else if (line[1] == 'n') {
7086 *line = '\n';
7087 skip = 1;
7088 }
7089 else if (line[1] == 't') {
7090 *line = '\t';
7091 skip = 1;
7092 }
7093 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007094 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 unsigned char hex1, hex2;
7096 hex1 = toupper(line[2]) - '0';
7097 hex2 = toupper(line[3]) - '0';
7098 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7099 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7100 *line = (hex1<<4) + hex2;
7101 skip = 3;
7102 }
7103 else {
7104 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007107 } else if (line[1] == '"') {
7108 *line = '"';
7109 skip = 1;
7110 } else if (line[1] == '\'') {
7111 *line = '\'';
7112 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007113 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7114 *line = '$';
7115 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007116 }
7117 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007118 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007119 end -= skip;
7120 }
7121 line++;
7122 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007123 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 /* end of string, end of loop */
7125 *line = 0;
7126 break;
7127 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007128 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007129 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007130 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007131 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007132 line++;
7133 args[++arg] = line;
7134 }
William Lallemandb2f07452015-05-12 14:27:13 +02007135 else if (dquote && *line == '$') {
7136 /* environment variables are evaluated inside double quotes */
7137 char *var_beg;
7138 char *var_end;
7139 char save_char;
7140 char *value;
7141 int val_len;
7142 int newlinesize;
7143 int braces = 0;
7144
7145 var_beg = line + 1;
7146 var_end = var_beg;
7147
7148 if (*var_beg == '{') {
7149 var_beg++;
7150 var_end++;
7151 braces = 1;
7152 }
7153
7154 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7155 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7156 err_code |= ERR_ALERT | ERR_FATAL;
7157 goto next_line; /* skip current line */
7158 }
7159
7160 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7161 var_end++;
7162
7163 save_char = *var_end;
7164 *var_end = '\0';
7165 value = getenv(var_beg);
7166 *var_end = save_char;
7167 val_len = value ? strlen(value) : 0;
7168
7169 if (braces) {
7170 if (*var_end == '}') {
7171 var_end++;
7172 braces = 0;
7173 } else {
7174 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7175 err_code |= ERR_ALERT | ERR_FATAL;
7176 goto next_line; /* skip current line */
7177 }
7178 }
7179
7180 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7181
7182 /* if not enough space in thisline */
7183 if (newlinesize > linesize) {
7184 char *newline;
7185
7186 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7187 if (newline == NULL) {
7188 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7189 err_code |= ERR_ALERT | ERR_FATAL;
7190 goto next_line; /* slip current line */
7191 }
7192 /* recompute pointers if realloc returns a new pointer */
7193 if (newline != thisline) {
7194 int i;
7195 int diff;
7196
7197 for (i = 0; i <= arg; i++) {
7198 diff = args[i] - thisline;
7199 args[i] = newline + diff;
7200 }
7201
7202 diff = var_end - thisline;
7203 var_end = newline + diff;
7204 diff = end - thisline;
7205 end = newline + diff;
7206 diff = line - thisline;
7207 line = newline + diff;
7208 thisline = newline;
7209 }
7210 linesize = newlinesize;
7211 }
7212
7213 /* insert value inside the line */
7214 memmove(line + val_len, var_end, end - var_end + 1);
7215 memcpy(line, value, val_len);
7216 end += val_len - (var_end - line);
7217 line += val_len;
7218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007219 else {
7220 line++;
7221 }
7222 }
William Lallemandb2f07452015-05-12 14:27:13 +02007223
William Lallemandf9873ba2015-05-05 17:37:14 +02007224 if (dquote) {
7225 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7226 err_code |= ERR_ALERT | ERR_FATAL;
7227 }
7228
7229 if (squote) {
7230 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7231 err_code |= ERR_ALERT | ERR_FATAL;
7232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007233
7234 /* empty line */
7235 if (!**args)
7236 continue;
7237
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007238 if (*line) {
7239 /* we had to stop due to too many args.
7240 * Let's terminate the string, print the offending part then cut the
7241 * last arg.
7242 */
7243 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7244 line++;
7245 *line = '\0';
7246
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007247 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007248 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007249 err_code |= ERR_ALERT | ERR_FATAL;
7250 args[arg] = line;
7251 }
7252
Willy Tarreau540abe42007-05-02 20:50:16 +02007253 /* zero out remaining args and ensure that at least one entry
7254 * is zeroed out.
7255 */
7256 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257 args[arg] = line;
7258 }
7259
Willy Tarreau3842f002009-06-14 11:39:52 +02007260 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007261 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007262 char *tmp;
7263
Willy Tarreau3842f002009-06-14 11:39:52 +02007264 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007265 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007266 for (arg=0; *args[arg+1]; arg++)
7267 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007268 *tmp = '\0'; // fix the next arg to \0
7269 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007270 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007271 else if (!strcmp(args[0], "default")) {
7272 kwm = KWM_DEF;
7273 for (arg=0; *args[arg+1]; arg++)
7274 args[arg] = args[arg+1]; // shift args after inversion
7275 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007276
William Lallemand0f99e342011-10-12 17:50:54 +02007277 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7278 strcmp(args[0], "log") != 0) {
7279 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007280 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007281 }
7282
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007283 /* detect section start */
7284 list_for_each_entry(ics, &sections, list) {
7285 if (strcmp(args[0], ics->section_name) == 0) {
7286 cursection = ics->section_name;
7287 cs = ics;
7288 break;
7289 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007290 }
7291
Willy Tarreaubaaee002006-06-26 02:48:02 +02007292 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007293 if (cs)
7294 err_code |= cs->section_parser(file, linenum, args, kwm);
7295 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007296 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007297 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007298 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007299
7300 if (err_code & ERR_ABORT)
7301 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007302 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007303 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007304 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007305 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007306 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007307}
7308
Willy Tarreau64ab6072014-09-16 12:17:36 +02007309/* This function propagates processes from frontend <from> to backend <to> so
7310 * that it is always guaranteed that a backend pointed to by a frontend is
7311 * bound to all of its processes. After that, if the target is a "listen"
7312 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007313 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007314 * checked first to ensure that <to> is already bound to all processes of
7315 * <from>, there is no risk of looping and we ensure to follow the shortest
7316 * path to the destination.
7317 *
7318 * It is possible to set <to> to NULL for the first call so that the function
7319 * takes care of visiting the initial frontend in <from>.
7320 *
7321 * It is important to note that the function relies on the fact that all names
7322 * have already been resolved.
7323 */
7324void propagate_processes(struct proxy *from, struct proxy *to)
7325{
7326 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007327
7328 if (to) {
7329 /* check whether we need to go down */
7330 if (from->bind_proc &&
7331 (from->bind_proc & to->bind_proc) == from->bind_proc)
7332 return;
7333
7334 if (!from->bind_proc && !to->bind_proc)
7335 return;
7336
7337 to->bind_proc = from->bind_proc ?
7338 (to->bind_proc | from->bind_proc) : 0;
7339
7340 /* now propagate down */
7341 from = to;
7342 }
7343
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007344 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007345 return;
7346
Willy Tarreauf6b70012014-12-18 14:00:43 +01007347 if (from->state == PR_STSTOPPED)
7348 return;
7349
Willy Tarreau64ab6072014-09-16 12:17:36 +02007350 /* default_backend */
7351 if (from->defbe.be)
7352 propagate_processes(from, from->defbe.be);
7353
7354 /* use_backend */
7355 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007356 if (rule->dynamic)
7357 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007358 to = rule->be.backend;
7359 propagate_processes(from, to);
7360 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007361}
7362
Willy Tarreaubb925012009-07-23 13:36:36 +02007363/*
7364 * Returns the error code, 0 if OK, or any combination of :
7365 * - ERR_ABORT: must abort ASAP
7366 * - ERR_FATAL: we can continue parsing but not start the service
7367 * - ERR_WARN: a warning has been emitted
7368 * - ERR_ALERT: an alert has been emitted
7369 * Only the two first ones can stop processing, the two others are just
7370 * indicators.
7371 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007372int check_config_validity()
7373{
7374 int cfgerr = 0;
7375 struct proxy *curproxy = NULL;
7376 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007377 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007378 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007379 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007380
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007381 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007382 /*
7383 * Now, check for the integrity of all that we have collected.
7384 */
7385
7386 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007387 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007388
Willy Tarreau193b8c62012-11-22 00:17:38 +01007389 if (!global.tune.max_http_hdr)
7390 global.tune.max_http_hdr = MAX_HTTP_HDR;
7391
7392 if (!global.tune.cookie_len)
7393 global.tune.cookie_len = CAPTURE_LEN;
7394
7395 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7396
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007397 /* Post initialisation of the users and groups lists. */
7398 err_code = userlist_postinit();
7399 if (err_code != ERR_NONE)
7400 goto out;
7401
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007402 /* first, we will invert the proxy list order */
7403 curproxy = NULL;
7404 while (proxy) {
7405 struct proxy *next;
7406
7407 next = proxy->next;
7408 proxy->next = curproxy;
7409 curproxy = proxy;
7410 if (!next)
7411 break;
7412 proxy = next;
7413 }
7414
Willy Tarreau419ead82014-09-16 13:41:21 +02007415 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007416 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007417 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007418 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007419 struct act_rule *trule;
7420 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007421 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007422 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007423 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007424
Willy Tarreau050536d2012-10-04 08:47:34 +02007425 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007426 /* proxy ID not set, use automatic numbering with first
7427 * spare entry starting with next_pxid.
7428 */
7429 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7430 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7431 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007432 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007433 next_pxid++;
7434
Willy Tarreau55ea7572007-06-17 19:56:27 +02007435
Willy Tarreaubaaee002006-06-26 02:48:02 +02007436 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007437 /* ensure we don't keep listeners uselessly bound */
7438 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007439 free((void *)curproxy->table.peers.name);
7440 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007441 continue;
7442 }
7443
Willy Tarreau102df612014-05-07 23:56:38 +02007444 /* Check multi-process mode compatibility for the current proxy */
7445
7446 if (curproxy->bind_proc) {
7447 /* an explicit bind-process was specified, let's check how many
7448 * processes remain.
7449 */
David Carliere6c39412015-07-02 07:00:17 +00007450 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007451
7452 curproxy->bind_proc &= nbits(global.nbproc);
7453 if (!curproxy->bind_proc && nbproc == 1) {
7454 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);
7455 curproxy->bind_proc = 1;
7456 }
7457 else if (!curproxy->bind_proc && nbproc > 1) {
7458 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);
7459 curproxy->bind_proc = 0;
7460 }
7461 }
7462
Willy Tarreau3d209582014-05-09 17:06:11 +02007463 /* check and reduce the bind-proc of each listener */
7464 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7465 unsigned long mask;
7466
7467 if (!bind_conf->bind_proc)
7468 continue;
7469
7470 mask = nbits(global.nbproc);
7471 if (curproxy->bind_proc)
7472 mask &= curproxy->bind_proc;
7473 /* mask cannot be null here thanks to the previous checks */
7474
David Carliere6c39412015-07-02 07:00:17 +00007475 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007476 bind_conf->bind_proc &= mask;
7477
7478 if (!bind_conf->bind_proc && nbproc == 1) {
7479 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",
7480 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7481 bind_conf->bind_proc = mask & ~(mask - 1);
7482 }
7483 else if (!bind_conf->bind_proc && nbproc > 1) {
7484 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",
7485 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7486 bind_conf->bind_proc = 0;
7487 }
7488 }
7489
Willy Tarreauff01a212009-03-15 13:46:16 +01007490 switch (curproxy->mode) {
7491 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007492 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007493 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007494 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7495 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007496 cfgerr++;
7497 }
7498
7499 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007500 Warning("config : servers will be ignored for %s '%s'.\n",
7501 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007502 break;
7503
7504 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007505 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007506 break;
7507
7508 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007509 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007510 break;
7511 }
7512
Willy Tarreauf3934b82015-08-11 11:36:45 +02007513 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7514 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7515 proxy_type_str(curproxy), curproxy->id);
7516 err_code |= ERR_WARN;
7517 }
7518
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007519 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007520 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007521 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007522 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7523 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007524 cfgerr++;
7525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007526#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007527 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007528 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7529 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007530 cfgerr++;
7531 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007532#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007533 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007534 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7535 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007536 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007537 }
7538 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007539 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007540 /* If no LB algo is set in a backend, and we're not in
7541 * transparent mode, dispatch mode nor proxy mode, we
7542 * want to use balance roundrobin by default.
7543 */
7544 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7545 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007546 }
7547 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007548
Willy Tarreau1620ec32011-08-06 17:05:02 +02007549 if (curproxy->options & PR_O_DISPATCH)
7550 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7551 else if (curproxy->options & PR_O_HTTP_PROXY)
7552 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7553 else if (curproxy->options & PR_O_TRANSP)
7554 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007555
Willy Tarreau1620ec32011-08-06 17:05:02 +02007556 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7557 if (curproxy->options & PR_O_DISABLE404) {
7558 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7559 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7560 err_code |= ERR_WARN;
7561 curproxy->options &= ~PR_O_DISABLE404;
7562 }
7563 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7564 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7565 "send-state", proxy_type_str(curproxy), curproxy->id);
7566 err_code |= ERR_WARN;
7567 curproxy->options &= ~PR_O2_CHK_SNDST;
7568 }
Willy Tarreauef781042010-01-27 11:53:01 +01007569 }
7570
Simon Horman98637e52014-06-20 12:30:16 +09007571 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7572 if (!global.external_check) {
7573 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7574 curproxy->id, "option external-check");
7575 cfgerr++;
7576 }
7577 if (!curproxy->check_command) {
7578 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7579 curproxy->id, "option external-check");
7580 cfgerr++;
7581 }
7582 }
7583
Simon Horman64e34162015-02-06 11:11:57 +09007584 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007585 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7586 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007587 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7588 "'email-alert myhostname', or 'email-alert to' "
7589 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007590 "to be present).\n",
7591 proxy_type_str(curproxy), curproxy->id);
7592 err_code |= ERR_WARN;
7593 free_email_alert(curproxy);
7594 }
7595 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007596 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007597 }
7598
Simon Horman98637e52014-06-20 12:30:16 +09007599 if (curproxy->check_command) {
7600 int clear = 0;
7601 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7602 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7603 "external-check command", proxy_type_str(curproxy), curproxy->id);
7604 err_code |= ERR_WARN;
7605 clear = 1;
7606 }
7607 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007608 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007609 curproxy->id, "external-check command");
7610 cfgerr++;
7611 }
7612 if (clear) {
7613 free(curproxy->check_command);
7614 curproxy->check_command = NULL;
7615 }
7616 }
7617
7618 if (curproxy->check_path) {
7619 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7620 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7621 "external-check path", proxy_type_str(curproxy), curproxy->id);
7622 err_code |= ERR_WARN;
7623 free(curproxy->check_path);
7624 curproxy->check_path = NULL;
7625 }
7626 }
7627
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007628 /* if a default backend was specified, let's find it */
7629 if (curproxy->defbe.name) {
7630 struct proxy *target;
7631
Willy Tarreauafb39922015-05-26 12:04:09 +02007632 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007633 if (!target) {
7634 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7635 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007636 cfgerr++;
7637 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007638 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7639 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007640 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007641 } else if (target->mode != curproxy->mode &&
7642 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7643
7644 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7645 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7646 curproxy->conf.file, curproxy->conf.line,
7647 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7648 target->conf.file, target->conf.line);
7649 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007650 } else {
7651 free(curproxy->defbe.name);
7652 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007653
7654 /* Emit a warning if this proxy also has some servers */
7655 if (curproxy->srv) {
7656 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7657 curproxy->id);
7658 err_code |= ERR_WARN;
7659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007660 }
7661 }
7662
Willy Tarreau55ea7572007-06-17 19:56:27 +02007663 /* find the target proxy for 'use_backend' rules */
7664 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007665 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007666 struct logformat_node *node;
7667 char *pxname;
7668
7669 /* Try to parse the string as a log format expression. If the result
7670 * of the parsing is only one entry containing a simple string, then
7671 * it's a standard string corresponding to a static rule, thus the
7672 * parsing is cancelled and be.name is restored to be resolved.
7673 */
7674 pxname = rule->be.name;
7675 LIST_INIT(&rule->be.expr);
7676 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7677 curproxy->conf.args.file, curproxy->conf.args.line);
7678 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7679
7680 if (!LIST_ISEMPTY(&rule->be.expr)) {
7681 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7682 rule->dynamic = 1;
7683 free(pxname);
7684 continue;
7685 }
7686 /* simple string: free the expression and fall back to static rule */
7687 free(node->arg);
7688 free(node);
7689 }
7690
7691 rule->dynamic = 0;
7692 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007693
Willy Tarreauafb39922015-05-26 12:04:09 +02007694 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007695 if (!target) {
7696 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7697 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007698 cfgerr++;
7699 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007700 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7701 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007702 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007703 } else if (target->mode != curproxy->mode &&
7704 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7705
7706 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7707 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7708 curproxy->conf.file, curproxy->conf.line,
7709 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7710 target->conf.file, target->conf.line);
7711 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007712 } else {
7713 free((void *)rule->be.name);
7714 rule->be.backend = target;
7715 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007716 }
7717
Willy Tarreau64ab6072014-09-16 12:17:36 +02007718 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007719 list_for_each_entry(srule, &curproxy->server_rules, list) {
7720 struct server *target = findserver(curproxy, srule->srv.name);
7721
7722 if (!target) {
7723 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7724 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7725 cfgerr++;
7726 continue;
7727 }
7728 free((void *)srule->srv.name);
7729 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007730 }
7731
Emeric Brunb982a3d2010-01-04 15:45:53 +01007732 /* find the target table for 'stick' rules */
7733 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7734 struct proxy *target;
7735
Emeric Brun1d33b292010-01-04 15:47:17 +01007736 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7737 if (mrule->flags & STK_IS_STORE)
7738 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7739
Emeric Brunb982a3d2010-01-04 15:45:53 +01007740 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007741 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007742 else
7743 target = curproxy;
7744
7745 if (!target) {
7746 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7747 curproxy->id, mrule->table.name);
7748 cfgerr++;
7749 }
7750 else if (target->table.size == 0) {
7751 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7752 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7753 cfgerr++;
7754 }
Willy Tarreau12785782012-04-27 21:37:17 +02007755 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7756 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007757 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7758 cfgerr++;
7759 }
7760 else {
7761 free((void *)mrule->table.name);
7762 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007763 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007764 }
7765 }
7766
7767 /* find the target table for 'store response' rules */
7768 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7769 struct proxy *target;
7770
Emeric Brun1d33b292010-01-04 15:47:17 +01007771 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7772
Emeric Brunb982a3d2010-01-04 15:45:53 +01007773 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007774 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007775 else
7776 target = curproxy;
7777
7778 if (!target) {
7779 Alert("Proxy '%s': unable to find store table '%s'.\n",
7780 curproxy->id, mrule->table.name);
7781 cfgerr++;
7782 }
7783 else if (target->table.size == 0) {
7784 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7785 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7786 cfgerr++;
7787 }
Willy Tarreau12785782012-04-27 21:37:17 +02007788 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7789 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007790 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7791 cfgerr++;
7792 }
7793 else {
7794 free((void *)mrule->table.name);
7795 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007796 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007797 }
7798 }
7799
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007800 /* find the target table for 'tcp-request' layer 4 rules */
7801 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7802 struct proxy *target;
7803
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007804 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007805 continue;
7806
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007807 if (trule->arg.trk_ctr.table.n)
7808 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007809 else
7810 target = curproxy;
7811
7812 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007813 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007814 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007815 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007816 cfgerr++;
7817 }
7818 else if (target->table.size == 0) {
7819 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007820 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007821 cfgerr++;
7822 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007823 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007824 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007825 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007826 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007827 cfgerr++;
7828 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007829 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007830 free(trule->arg.trk_ctr.table.n);
7831 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007832 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007833 * to pass a list of counters to track and allocate them right here using
7834 * stktable_alloc_data_type().
7835 */
7836 }
7837 }
7838
Willy Tarreau620408f2016-10-21 16:37:51 +02007839 /* find the target table for 'tcp-request' layer 5 rules */
7840 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7841 struct proxy *target;
7842
7843 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7844 continue;
7845
7846 if (trule->arg.trk_ctr.table.n)
7847 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7848 else
7849 target = curproxy;
7850
7851 if (!target) {
7852 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7853 curproxy->id, trule->arg.trk_ctr.table.n,
7854 tcp_trk_idx(trule->action));
7855 cfgerr++;
7856 }
7857 else if (target->table.size == 0) {
7858 Alert("Proxy '%s': table '%s' used but not configured.\n",
7859 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7860 cfgerr++;
7861 }
7862 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7863 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7864 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7865 tcp_trk_idx(trule->action));
7866 cfgerr++;
7867 }
7868 else {
7869 free(trule->arg.trk_ctr.table.n);
7870 trule->arg.trk_ctr.table.t = &target->table;
7871 /* Note: if we decide to enhance the track-sc syntax, we may be able
7872 * to pass a list of counters to track and allocate them right here using
7873 * stktable_alloc_data_type().
7874 */
7875 }
7876 }
7877
Willy Tarreaud1f96522010-08-03 19:34:32 +02007878 /* find the target table for 'tcp-request' layer 6 rules */
7879 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7880 struct proxy *target;
7881
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007882 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007883 continue;
7884
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007885 if (trule->arg.trk_ctr.table.n)
7886 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007887 else
7888 target = curproxy;
7889
7890 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007891 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007893 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007894 cfgerr++;
7895 }
7896 else if (target->table.size == 0) {
7897 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007898 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007899 cfgerr++;
7900 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007901 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007902 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007903 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007904 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007905 cfgerr++;
7906 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007907 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007908 free(trule->arg.trk_ctr.table.n);
7909 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007910 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007911 * to pass a list of counters to track and allocate them right here using
7912 * stktable_alloc_data_type().
7913 */
7914 }
7915 }
7916
Baptiste Assmanne9544932015-11-03 23:31:35 +01007917 /* parse http-request capture rules to ensure id really exists */
7918 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7919 if (hrqrule->action != ACT_CUSTOM ||
7920 hrqrule->action_ptr != http_action_req_capture_by_id)
7921 continue;
7922
7923 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7924 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7925 curproxy->id, hrqrule->arg.capid.idx);
7926 cfgerr++;
7927 }
7928 }
7929
7930 /* parse http-response capture rules to ensure id really exists */
7931 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7932 if (hrqrule->action != ACT_CUSTOM ||
7933 hrqrule->action_ptr != http_action_res_capture_by_id)
7934 continue;
7935
7936 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7937 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7938 curproxy->id, hrqrule->arg.capid.idx);
7939 cfgerr++;
7940 }
7941 }
7942
Willy Tarreau09448f72014-06-25 18:12:15 +02007943 /* find the target table for 'http-request' layer 7 rules */
7944 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7945 struct proxy *target;
7946
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007947 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007948 continue;
7949
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007950 if (hrqrule->arg.trk_ctr.table.n)
7951 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007952 else
7953 target = curproxy;
7954
7955 if (!target) {
7956 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007957 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007958 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007959 cfgerr++;
7960 }
7961 else if (target->table.size == 0) {
7962 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007963 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007964 cfgerr++;
7965 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007966 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007967 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007968 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007969 http_trk_idx(hrqrule->action));
7970 cfgerr++;
7971 }
7972 else {
7973 free(hrqrule->arg.trk_ctr.table.n);
7974 hrqrule->arg.trk_ctr.table.t = &target->table;
7975 /* Note: if we decide to enhance the track-sc syntax, we may be able
7976 * to pass a list of counters to track and allocate them right here using
7977 * stktable_alloc_data_type().
7978 */
7979 }
7980 }
7981
7982 /* find the target table for 'http-response' layer 7 rules */
7983 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7984 struct proxy *target;
7985
7986 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7987 continue;
7988
7989 if (hrqrule->arg.trk_ctr.table.n)
7990 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7991 else
7992 target = curproxy;
7993
7994 if (!target) {
7995 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7996 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7997 http_trk_idx(hrqrule->action));
7998 cfgerr++;
7999 }
8000 else if (target->table.size == 0) {
8001 Alert("Proxy '%s': table '%s' used but not configured.\n",
8002 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8003 cfgerr++;
8004 }
8005 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8006 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8007 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8008 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008009 cfgerr++;
8010 }
8011 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008012 free(hrqrule->arg.trk_ctr.table.n);
8013 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008014 /* Note: if we decide to enhance the track-sc syntax, we may be able
8015 * to pass a list of counters to track and allocate them right here using
8016 * stktable_alloc_data_type().
8017 */
8018 }
8019 }
8020
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008021 /* move any "block" rules at the beginning of the http-request rules */
8022 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8023 /* insert block_rules into http_req_rules at the beginning */
8024 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8025 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8026 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8027 curproxy->http_req_rules.n = curproxy->block_rules.n;
8028 LIST_INIT(&curproxy->block_rules);
8029 }
8030
Emeric Brun32da3c42010-09-23 18:39:19 +02008031 if (curproxy->table.peers.name) {
8032 struct peers *curpeers = peers;
8033
8034 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8035 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8036 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008037 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008038 break;
8039 }
8040 }
8041
8042 if (!curpeers) {
8043 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8044 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008045 free((void *)curproxy->table.peers.name);
8046 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008047 cfgerr++;
8048 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008049 else if (curpeers->state == PR_STSTOPPED) {
8050 /* silently disable this peers section */
8051 curproxy->table.peers.p = NULL;
8052 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008053 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008054 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8055 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008056 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008057 cfgerr++;
8058 }
8059 }
8060
Simon Horman9dc49962015-01-30 11:22:59 +09008061
8062 if (curproxy->email_alert.mailers.name) {
8063 struct mailers *curmailers = mailers;
8064
8065 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8066 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8067 free(curproxy->email_alert.mailers.name);
8068 curproxy->email_alert.mailers.m = curmailers;
8069 curmailers->users++;
8070 break;
8071 }
8072 }
8073
8074 if (!curmailers) {
8075 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8076 curproxy->id, curproxy->email_alert.mailers.name);
8077 free_email_alert(curproxy);
8078 cfgerr++;
8079 }
8080 }
8081
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008082 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008083 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008084 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8085 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8086 "proxy", curproxy->id);
8087 cfgerr++;
8088 goto out_uri_auth_compat;
8089 }
8090
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008091 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008092 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008093 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008094 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008095
Willy Tarreau95fa4692010-02-01 13:05:50 +01008096 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8097 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008098
8099 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008100 uri_auth_compat_req[i++] = "realm";
8101 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8102 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008103
Willy Tarreau95fa4692010-02-01 13:05:50 +01008104 uri_auth_compat_req[i++] = "unless";
8105 uri_auth_compat_req[i++] = "{";
8106 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8107 uri_auth_compat_req[i++] = "}";
8108 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008109
Willy Tarreauff011f22011-01-06 17:51:27 +01008110 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8111 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008112 cfgerr++;
8113 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008114 }
8115
Willy Tarreauff011f22011-01-06 17:51:27 +01008116 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008117
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008118 if (curproxy->uri_auth->auth_realm) {
8119 free(curproxy->uri_auth->auth_realm);
8120 curproxy->uri_auth->auth_realm = NULL;
8121 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008122
8123 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008124 }
8125out_uri_auth_compat:
8126
Dragan Dosen43885c72015-10-01 13:18:13 +02008127 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008128 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008129 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8130 if (!curproxy->conf.logformat_sd_string) {
8131 /* set the default logformat_sd_string */
8132 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8133 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008134 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008135 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008136 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008137
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008138 /* compile the log format */
8139 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008140 if (curproxy->conf.logformat_string != default_http_log_format &&
8141 curproxy->conf.logformat_string != default_tcp_log_format &&
8142 curproxy->conf.logformat_string != clf_http_log_format)
8143 free(curproxy->conf.logformat_string);
8144 curproxy->conf.logformat_string = NULL;
8145 free(curproxy->conf.lfs_file);
8146 curproxy->conf.lfs_file = NULL;
8147 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008148
8149 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8150 free(curproxy->conf.logformat_sd_string);
8151 curproxy->conf.logformat_sd_string = NULL;
8152 free(curproxy->conf.lfsd_file);
8153 curproxy->conf.lfsd_file = NULL;
8154 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008155 }
8156
Willy Tarreau62a61232013-04-12 18:13:46 +02008157 if (curproxy->conf.logformat_string) {
8158 curproxy->conf.args.ctx = ARGC_LOG;
8159 curproxy->conf.args.file = curproxy->conf.lfs_file;
8160 curproxy->conf.args.line = curproxy->conf.lfs_line;
8161 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008162 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008163 curproxy->conf.args.file = NULL;
8164 curproxy->conf.args.line = 0;
8165 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008166
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008167 if (curproxy->conf.logformat_sd_string) {
8168 curproxy->conf.args.ctx = ARGC_LOGSD;
8169 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8170 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8171 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8172 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8173 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8174 curproxy->conf.args.file = NULL;
8175 curproxy->conf.args.line = 0;
8176 }
8177
Willy Tarreau62a61232013-04-12 18:13:46 +02008178 if (curproxy->conf.uniqueid_format_string) {
8179 curproxy->conf.args.ctx = ARGC_UIF;
8180 curproxy->conf.args.file = curproxy->conf.uif_file;
8181 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008182 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008183 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008184 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008185 curproxy->conf.args.file = NULL;
8186 curproxy->conf.args.line = 0;
8187 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008188
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008189 /* only now we can check if some args remain unresolved.
8190 * This must be done after the users and groups resolution.
8191 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008192 cfgerr += smp_resolve_args(curproxy);
8193 if (!cfgerr)
8194 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008195
Willy Tarreau2738a142006-07-08 17:28:09 +02008196 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008197 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008198 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008199 (!curproxy->timeout.connect ||
8200 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008201 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008202 " | While not properly invalid, you will certainly encounter various problems\n"
8203 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008204 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008205 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008206 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008207 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008208
Willy Tarreau1fa31262007-12-03 00:36:16 +01008209 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8210 * We must still support older configurations, so let's find out whether those
8211 * parameters have been set or must be copied from contimeouts.
8212 */
8213 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008214 if (!curproxy->timeout.tarpit ||
8215 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008216 /* tarpit timeout not set. We search in the following order:
8217 * default.tarpit, curr.connect, default.connect.
8218 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008219 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008220 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008221 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008222 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008223 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008224 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008225 }
8226 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008227 (!curproxy->timeout.queue ||
8228 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008229 /* queue timeout not set. We search in the following order:
8230 * default.queue, curr.connect, default.connect.
8231 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008232 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008233 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008234 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008235 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008236 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008237 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008238 }
8239 }
8240
Willy Tarreau1620ec32011-08-06 17:05:02 +02008241 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008242 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008243 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008244 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008245 }
8246
Willy Tarreau215663d2014-06-13 18:30:23 +02008247 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8248 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8249 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8250 proxy_type_str(curproxy), curproxy->id);
8251 err_code |= ERR_WARN;
8252 }
8253
Willy Tarreau193b8c62012-11-22 00:17:38 +01008254 /* ensure that cookie capture length is not too large */
8255 if (curproxy->capture_len >= global.tune.cookie_len) {
8256 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8257 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8258 err_code |= ERR_WARN;
8259 curproxy->capture_len = global.tune.cookie_len - 1;
8260 }
8261
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008262 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008263 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008264 curproxy->req_cap_pool = create_pool("ptrcap",
8265 curproxy->nb_req_cap * sizeof(char *),
8266 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008267 }
8268
8269 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008270 curproxy->rsp_cap_pool = create_pool("ptrcap",
8271 curproxy->nb_rsp_cap * sizeof(char *),
8272 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008273 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008274
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008275 switch (curproxy->load_server_state_from_file) {
8276 case PR_SRV_STATE_FILE_UNSPEC:
8277 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8278 break;
8279 case PR_SRV_STATE_FILE_GLOBAL:
8280 if (!global.server_state_file) {
8281 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",
8282 curproxy->id);
8283 err_code |= ERR_WARN;
8284 }
8285 break;
8286 }
8287
Willy Tarreaubaaee002006-06-26 02:48:02 +02008288 /* first, we will invert the servers list order */
8289 newsrv = NULL;
8290 while (curproxy->srv) {
8291 struct server *next;
8292
8293 next = curproxy->srv->next;
8294 curproxy->srv->next = newsrv;
8295 newsrv = curproxy->srv;
8296 if (!next)
8297 break;
8298 curproxy->srv = next;
8299 }
8300
Willy Tarreau17edc812014-01-03 12:14:34 +01008301 /* Check that no server name conflicts. This causes trouble in the stats.
8302 * We only emit a warning for the first conflict affecting each server,
8303 * in order to avoid combinatory explosion if all servers have the same
8304 * name. We do that only for servers which do not have an explicit ID,
8305 * because these IDs were made also for distinguishing them and we don't
8306 * want to annoy people who correctly manage them.
8307 */
8308 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8309 struct server *other_srv;
8310
8311 if (newsrv->puid)
8312 continue;
8313
8314 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8315 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8316 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8317 newsrv->conf.file, newsrv->conf.line,
8318 proxy_type_str(curproxy), curproxy->id,
8319 newsrv->id, other_srv->conf.line);
8320 break;
8321 }
8322 }
8323 }
8324
Willy Tarreaudd701652010-05-25 23:03:02 +02008325 /* assign automatic UIDs to servers which don't have one yet */
8326 next_id = 1;
8327 newsrv = curproxy->srv;
8328 while (newsrv != NULL) {
8329 if (!newsrv->puid) {
8330 /* server ID not set, use automatic numbering with first
8331 * spare entry starting with next_svid.
8332 */
8333 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8334 newsrv->conf.id.key = newsrv->puid = next_id;
8335 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8336 }
8337 next_id++;
8338 newsrv = newsrv->next;
8339 }
8340
Willy Tarreau20697042007-11-15 23:26:18 +01008341 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008342 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008343
Willy Tarreau62c3be22012-01-20 13:12:32 +01008344 /*
8345 * If this server supports a maxconn parameter, it needs a dedicated
8346 * tasks to fill the emptied slots when a connection leaves.
8347 * Also, resolve deferred tracking dependency if needed.
8348 */
8349 newsrv = curproxy->srv;
8350 while (newsrv != NULL) {
8351 if (newsrv->minconn > newsrv->maxconn) {
8352 /* Only 'minconn' was specified, or it was higher than or equal
8353 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8354 * this will avoid further useless expensive computations.
8355 */
8356 newsrv->maxconn = newsrv->minconn;
8357 } else if (newsrv->maxconn && !newsrv->minconn) {
8358 /* minconn was not specified, so we set it to maxconn */
8359 newsrv->minconn = newsrv->maxconn;
8360 }
8361
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008362#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008363 if (newsrv->use_ssl || newsrv->check.use_ssl)
8364 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008365#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008366
Willy Tarreau2f075e92013-12-03 11:11:34 +01008367 /* set the check type on the server */
8368 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8369
Willy Tarreau62c3be22012-01-20 13:12:32 +01008370 if (newsrv->trackit) {
8371 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008372 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008373 char *pname, *sname;
8374
8375 pname = newsrv->trackit;
8376 sname = strrchr(pname, '/');
8377
8378 if (sname)
8379 *sname++ = '\0';
8380 else {
8381 sname = pname;
8382 pname = NULL;
8383 }
8384
8385 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008386 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008387 if (!px) {
8388 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8389 proxy_type_str(curproxy), curproxy->id,
8390 newsrv->id, pname);
8391 cfgerr++;
8392 goto next_srv;
8393 }
8394 } else
8395 px = curproxy;
8396
8397 srv = findserver(px, sname);
8398 if (!srv) {
8399 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8400 proxy_type_str(curproxy), curproxy->id,
8401 newsrv->id, sname);
8402 cfgerr++;
8403 goto next_srv;
8404 }
8405
Willy Tarreau32091232014-05-16 13:52:00 +02008406 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8407 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8408 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008409 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008410 "tracking as it does not have any check nor agent enabled.\n",
8411 proxy_type_str(curproxy), curproxy->id,
8412 newsrv->id, px->id, srv->id);
8413 cfgerr++;
8414 goto next_srv;
8415 }
8416
8417 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8418
8419 if (loop) {
8420 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8421 "belongs to a tracking chain looping back to %s/%s.\n",
8422 proxy_type_str(curproxy), curproxy->id,
8423 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008424 cfgerr++;
8425 goto next_srv;
8426 }
8427
8428 if (curproxy != px &&
8429 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8430 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8431 "tracking: disable-on-404 option inconsistency.\n",
8432 proxy_type_str(curproxy), curproxy->id,
8433 newsrv->id, px->id, srv->id);
8434 cfgerr++;
8435 goto next_srv;
8436 }
8437
8438 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008439 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008440 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008441 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008442 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008443 }
8444
8445 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008446 newsrv->tracknext = srv->trackers;
8447 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008448
8449 free(newsrv->trackit);
8450 newsrv->trackit = NULL;
8451 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008452
8453 /*
8454 * resolve server's resolvers name and update the resolvers pointer
8455 * accordingly
8456 */
8457 if (newsrv->resolvers_id) {
8458 struct dns_resolvers *curr_resolvers;
8459 int found;
8460
8461 found = 0;
8462 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8463 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8464 found = 1;
8465 break;
8466 }
8467 }
8468
8469 if (!found) {
8470 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8471 proxy_type_str(curproxy), curproxy->id,
8472 newsrv->id, newsrv->resolvers_id);
8473 cfgerr++;
8474 } else {
8475 free(newsrv->resolvers_id);
8476 newsrv->resolvers_id = NULL;
8477 if (newsrv->resolution)
8478 newsrv->resolution->resolvers = curr_resolvers;
8479 }
8480 }
8481 else {
8482 /* if no resolvers section associated to this server
8483 * we can clean up the associated resolution structure
8484 */
8485 if (newsrv->resolution) {
8486 free(newsrv->resolution->hostname_dn);
8487 newsrv->resolution->hostname_dn = NULL;
8488 free(newsrv->resolution);
8489 newsrv->resolution = NULL;
8490 }
8491 }
8492
Willy Tarreau62c3be22012-01-20 13:12:32 +01008493 next_srv:
8494 newsrv = newsrv->next;
8495 }
8496
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008497 /* We have to initialize the server lookup mechanism depending
8498 * on what LB algorithm was choosen.
8499 */
8500
8501 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8502 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8503 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008504 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8505 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8506 init_server_map(curproxy);
8507 } else {
8508 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8509 fwrr_init_server_groups(curproxy);
8510 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008511 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008512
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008513 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008514 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8515 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8516 fwlc_init_server_tree(curproxy);
8517 } else {
8518 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8519 fas_init_server_tree(curproxy);
8520 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008521 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008522
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008523 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008524 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8525 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8526 chash_init_server_tree(curproxy);
8527 } else {
8528 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8529 init_server_map(curproxy);
8530 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008531 break;
8532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008533
8534 if (curproxy->options & PR_O_LOGASAP)
8535 curproxy->to_log &= ~LW_BYTES;
8536
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008537 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008538 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8539 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008540 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8541 proxy_type_str(curproxy), curproxy->id);
8542 err_code |= ERR_WARN;
8543 }
8544
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008545 if (curproxy->mode != PR_MODE_HTTP) {
8546 int optnum;
8547
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008548 if (curproxy->uri_auth) {
8549 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8550 proxy_type_str(curproxy), curproxy->id);
8551 err_code |= ERR_WARN;
8552 curproxy->uri_auth = NULL;
8553 }
8554
Willy Tarreau87cf5142011-08-19 22:57:24 +02008555 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008556 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8557 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8558 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008559 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008560 }
8561
8562 if (curproxy->options & PR_O_ORGTO) {
8563 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8564 "originalto", proxy_type_str(curproxy), curproxy->id);
8565 err_code |= ERR_WARN;
8566 curproxy->options &= ~PR_O_ORGTO;
8567 }
8568
8569 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8570 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8571 (curproxy->cap & cfg_opts[optnum].cap) &&
8572 (curproxy->options & cfg_opts[optnum].val)) {
8573 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8574 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8575 err_code |= ERR_WARN;
8576 curproxy->options &= ~cfg_opts[optnum].val;
8577 }
8578 }
8579
8580 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8581 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8582 (curproxy->cap & cfg_opts2[optnum].cap) &&
8583 (curproxy->options2 & cfg_opts2[optnum].val)) {
8584 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8585 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8586 err_code |= ERR_WARN;
8587 curproxy->options2 &= ~cfg_opts2[optnum].val;
8588 }
8589 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008590
Willy Tarreau29fbe512015-08-20 19:35:14 +02008591#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008592 if (curproxy->conn_src.bind_hdr_occ) {
8593 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008594 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008595 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008596 err_code |= ERR_WARN;
8597 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008598#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008599 }
8600
Willy Tarreaubaaee002006-06-26 02:48:02 +02008601 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008602 * ensure that we're not cross-dressing a TCP server into HTTP.
8603 */
8604 newsrv = curproxy->srv;
8605 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008606 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008607 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8608 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008609 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008610 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008611
Willy Tarreau0cec3312011-10-31 13:49:26 +01008612 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8613 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8614 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8615 err_code |= ERR_WARN;
8616 }
8617
Willy Tarreauc93cd162014-05-13 15:54:22 +02008618 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008619 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8620 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8621 err_code |= ERR_WARN;
8622 }
8623
Willy Tarreau29fbe512015-08-20 19:35:14 +02008624#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008625 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8626 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008627 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 +01008628 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008629 err_code |= ERR_WARN;
8630 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008631#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008632 newsrv = newsrv->next;
8633 }
8634
Willy Tarreaue42bd962014-09-16 16:21:19 +02008635 /* check if we have a frontend with "tcp-request content" looking at L7
8636 * with no inspect-delay
8637 */
8638 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8639 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008640 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008641 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008642 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008643 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008644 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008645 break;
8646 }
8647
8648 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8649 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8650 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8651 " This means that these rules will randomly find their contents. This can be fixed by"
8652 " setting the tcp-request inspect-delay.\n",
8653 proxy_type_str(curproxy), curproxy->id);
8654 err_code |= ERR_WARN;
8655 }
8656 }
8657
Christopher Fauletd7c91962015-04-30 11:48:27 +02008658 /* Check filter configuration, if any */
8659 cfgerr += flt_check(curproxy);
8660
Willy Tarreauc1a21672009-08-16 22:37:44 +02008661 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008662 if (!curproxy->accept)
8663 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008664
Willy Tarreauc1a21672009-08-16 22:37:44 +02008665 if (curproxy->tcp_req.inspect_delay ||
8666 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008667 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008668
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008669 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008670 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008671 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008672 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008673
8674 /* both TCP and HTTP must check switching rules */
8675 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008676
8677 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008678 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008679 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8680 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008681 if (curproxy->mode == PR_MODE_HTTP) {
8682 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8683 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8684 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008685 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008686 }
8687
8688 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008689 if (curproxy->tcp_req.inspect_delay ||
8690 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8691 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8692
Emeric Brun97679e72010-09-23 17:56:44 +02008693 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8694 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8695
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008696 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008697 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008698 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008699 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008700
8701 /* If the backend does requires RDP cookie persistence, we have to
8702 * enable the corresponding analyser.
8703 */
8704 if (curproxy->options2 & PR_O2_RDPC_PRST)
8705 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008706
8707 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008708 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008709 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8710 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008711 if (curproxy->mode == PR_MODE_HTTP) {
8712 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8713 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8714 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008715 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008716 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008717 }
8718
8719 /***********************************************************/
8720 /* At this point, target names have already been resolved. */
8721 /***********************************************************/
8722
8723 /* Check multi-process mode compatibility */
8724
8725 if (global.nbproc > 1 && global.stats_fe) {
8726 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8727 unsigned long mask;
8728
8729 mask = nbits(global.nbproc);
8730 if (global.stats_fe->bind_proc)
8731 mask &= global.stats_fe->bind_proc;
8732
8733 if (bind_conf->bind_proc)
8734 mask &= bind_conf->bind_proc;
8735
8736 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008737 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008738 break;
8739 }
8740 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8741 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");
8742 }
8743 }
8744
8745 /* Make each frontend inherit bind-process from its listeners when not specified. */
8746 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8747 if (curproxy->bind_proc)
8748 continue;
8749
8750 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8751 unsigned long mask;
8752
Willy Tarreaue428b082015-05-04 21:57:58 +02008753 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008754 curproxy->bind_proc |= mask;
8755 }
8756
8757 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008758 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008759 }
8760
8761 if (global.stats_fe) {
8762 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8763 unsigned long mask;
8764
Cyril Bonté06181952016-02-24 00:14:54 +01008765 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008766 global.stats_fe->bind_proc |= mask;
8767 }
8768 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008769 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008770 }
8771
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008772 /* propagate bindings from frontends to backends. Don't do it if there
8773 * are any fatal errors as we must not call it with unresolved proxies.
8774 */
8775 if (!cfgerr) {
8776 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8777 if (curproxy->cap & PR_CAP_FE)
8778 propagate_processes(curproxy, NULL);
8779 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008780 }
8781
8782 /* Bind each unbound backend to all processes when not specified. */
8783 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8784 if (curproxy->bind_proc)
8785 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008786 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008787 }
8788
8789 /*******************************************************/
8790 /* At this step, all proxies have a non-null bind_proc */
8791 /*******************************************************/
8792
8793 /* perform the final checks before creating tasks */
8794
8795 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8796 struct listener *listener;
8797 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008798
Emeric Brunc52962f2012-11-15 18:28:02 +01008799#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008800 /* Configure SSL for each bind line.
8801 * Note: if configuration fails at some point, the ->ctx member
8802 * remains NULL so that listeners can later detach.
8803 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008804 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008805 int alloc_ctx;
8806
Emeric Brunc52962f2012-11-15 18:28:02 +01008807 if (!bind_conf->is_ssl) {
8808 if (bind_conf->default_ctx) {
8809 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8810 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8811 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008812 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008813 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008814 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008815 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008816 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008817 cfgerr++;
8818 continue;
8819 }
8820
Emeric Brun8dc60392014-05-09 13:52:00 +02008821 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008822 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008823 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8824 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");
8825 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008826 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008827 cfgerr++;
8828 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008829 }
8830
Emeric Brunfc0421f2012-09-07 17:30:07 +02008831 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008832 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008833
8834 /* initialize CA variables if the certificates generation is enabled */
8835 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008836 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008837#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008838
Willy Tarreaue6b98942007-10-29 01:09:36 +01008839 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008840 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008841 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008842 int nbproc;
8843
8844 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008845 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008846 nbits(global.nbproc));
8847
8848 if (!nbproc) /* no intersection between listener and frontend */
8849 nbproc = 1;
8850
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008851 if (!listener->luid) {
8852 /* listener ID not set, use automatic numbering with first
8853 * spare entry starting with next_luid.
8854 */
8855 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8856 listener->conf.id.key = listener->luid = next_id;
8857 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008858 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008859 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008860
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008861 /* enable separate counters */
8862 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008863 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008864 if (!listener->name)
8865 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008866 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008867
Willy Tarreaue6b98942007-10-29 01:09:36 +01008868 if (curproxy->options & PR_O_TCP_NOLING)
8869 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008870 if (!listener->maxconn)
8871 listener->maxconn = curproxy->maxconn;
8872 if (!listener->backlog)
8873 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008874 if (!listener->maxaccept)
8875 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8876
8877 /* we want to have an optimal behaviour on single process mode to
8878 * maximize the work at once, but in multi-process we want to keep
8879 * some fairness between processes, so we target half of the max
8880 * number of events to be balanced over all the processes the proxy
8881 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8882 * used to disable the limit.
8883 */
8884 if (listener->maxaccept > 0) {
8885 if (nbproc > 1)
8886 listener->maxaccept = (listener->maxaccept + 1) / 2;
8887 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8888 }
8889
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008890 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008891 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008892 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008893 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008894
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008895 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008896 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008897
Willy Tarreau620408f2016-10-21 16:37:51 +02008898 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8899 listener->options |= LI_O_TCP_L5_RULES;
8900
Willy Tarreaude3041d2010-05-31 10:56:17 +02008901 if (curproxy->mon_mask.s_addr)
8902 listener->options |= LI_O_CHK_MONNET;
8903
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008904 /* smart accept mode is automatic in HTTP mode */
8905 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008906 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008907 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8908 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008909 }
8910
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008911 /* Release unused SSL configs */
8912 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8913 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008914 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008915#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008916 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008917 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008918 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008919 free(bind_conf->ca_sign_file);
8920 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008921 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008922 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008923 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008924 if(bind_conf->keys_ref) {
8925 free(bind_conf->keys_ref->filename);
8926 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008927 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008928 free(bind_conf->keys_ref);
8929 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008930#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008931 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008932
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008933 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008934 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008935 int count, maxproc = 0;
8936
8937 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008938 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008939 if (count > maxproc)
8940 maxproc = count;
8941 }
8942 /* backends have 0, frontends have 1 or more */
8943 if (maxproc != 1)
8944 Warning("Proxy '%s': in multi-process mode, stats will be"
8945 " limited to process assigned to the current request.\n",
8946 curproxy->id);
8947
Willy Tarreau102df612014-05-07 23:56:38 +02008948 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8949 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8950 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008951 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008952 }
Willy Tarreau102df612014-05-07 23:56:38 +02008953 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8954 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8955 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008956 }
8957 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008958
8959 /* create the task associated with the proxy */
8960 curproxy->task = task_new();
8961 if (curproxy->task) {
8962 curproxy->task->context = curproxy;
8963 curproxy->task->process = manage_proxy;
8964 /* no need to queue, it will be done automatically if some
8965 * listener gets limited.
8966 */
8967 curproxy->task->expire = TICK_ETERNITY;
8968 } else {
8969 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8970 curproxy->id);
8971 cfgerr++;
8972 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008973 }
8974
Willy Tarreaufbb78422011-06-05 15:38:35 +02008975 /* automatically compute fullconn if not set. We must not do it in the
8976 * loop above because cross-references are not yet fully resolved.
8977 */
8978 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8979 /* If <fullconn> is not set, let's set it to 10% of the sum of
8980 * the possible incoming frontend's maxconns.
8981 */
8982 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8983 struct proxy *fe;
8984 int total = 0;
8985
8986 /* sum up the number of maxconns of frontends which
8987 * reference this backend at least once or which are
8988 * the same one ('listen').
8989 */
8990 for (fe = proxy; fe; fe = fe->next) {
8991 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008992 int found = 0;
8993
8994 if (!(fe->cap & PR_CAP_FE))
8995 continue;
8996
8997 if (fe == curproxy) /* we're on a "listen" instance */
8998 found = 1;
8999
9000 if (fe->defbe.be == curproxy) /* "default_backend" */
9001 found = 1;
9002
9003 /* check if a "use_backend" rule matches */
9004 if (!found) {
9005 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009006 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009007 found = 1;
9008 break;
9009 }
9010 }
9011 }
9012
Willy Tarreaufbb78422011-06-05 15:38:35 +02009013 /* now we've checked all possible ways to reference a backend
9014 * from a frontend.
9015 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009016 if (!found)
9017 continue;
9018 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009019 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009020 /* we have the sum of the maxconns in <total>. We only
9021 * keep 10% of that sum to set the default fullconn, with
9022 * a hard minimum of 1 (to avoid a divide by zero).
9023 */
9024 curproxy->fullconn = (total + 9) / 10;
9025 if (!curproxy->fullconn)
9026 curproxy->fullconn = 1;
9027 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009028 }
9029
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009030 /*
9031 * Recount currently required checks.
9032 */
9033
9034 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9035 int optnum;
9036
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009037 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9038 if (curproxy->options & cfg_opts[optnum].val)
9039 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009040
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009041 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9042 if (curproxy->options2 & cfg_opts2[optnum].val)
9043 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009044 }
9045
Willy Tarreau0fca4832015-05-01 19:12:05 +02009046 /* compute the required process bindings for the peers */
9047 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9048 if (curproxy->table.peers.p)
9049 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9050
Willy Tarreau122541c2011-09-07 21:24:49 +02009051 if (peers) {
9052 struct peers *curpeers = peers, **last;
9053 struct peer *p, *pb;
9054
Willy Tarreau1e273012015-05-01 19:15:17 +02009055 /* Remove all peers sections which don't have a valid listener,
9056 * which are not used by any table, or which are bound to more
9057 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009058 */
9059 last = &peers;
9060 while (*last) {
9061 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009062
9063 if (curpeers->state == PR_STSTOPPED) {
9064 /* the "disabled" keyword was present */
9065 if (curpeers->peers_fe)
9066 stop_proxy(curpeers->peers_fe);
9067 curpeers->peers_fe = NULL;
9068 }
9069 else if (!curpeers->peers_fe) {
9070 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9071 curpeers->id, localpeer);
9072 }
David Carliere6c39412015-07-02 07:00:17 +00009073 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009074 /* either it's totally stopped or too much used */
9075 if (curpeers->peers_fe->bind_proc) {
9076 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009077 "running in different processes (%d different ones). "
9078 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009079 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009080 cfgerr++;
9081 }
9082 stop_proxy(curpeers->peers_fe);
9083 curpeers->peers_fe = NULL;
9084 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009085 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009086 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009087 last = &curpeers->next;
9088 continue;
9089 }
9090
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009091 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009092 p = curpeers->remote;
9093 while (p) {
9094 pb = p->next;
9095 free(p->id);
9096 free(p);
9097 p = pb;
9098 }
9099
9100 /* Destroy and unlink this curpeers section.
9101 * Note: curpeers is backed up into *last.
9102 */
9103 free(curpeers->id);
9104 curpeers = curpeers->next;
9105 free(*last);
9106 *last = curpeers;
9107 }
9108 }
9109
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009110 /* initialize stick-tables on backend capable proxies. This must not
9111 * be done earlier because the data size may be discovered while parsing
9112 * other proxies.
9113 */
9114 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9115 if (curproxy->state == PR_STSTOPPED)
9116 continue;
9117
9118 if (!stktable_init(&curproxy->table)) {
9119 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9120 cfgerr++;
9121 }
9122 }
9123
Simon Horman0d16a402015-01-30 11:22:58 +09009124 if (mailers) {
9125 struct mailers *curmailers = mailers, **last;
9126 struct mailer *m, *mb;
9127
9128 /* Remove all mailers sections which don't have a valid listener.
9129 * This can happen when a mailers section is never referenced.
9130 */
9131 last = &mailers;
9132 while (*last) {
9133 curmailers = *last;
9134 if (curmailers->users) {
9135 last = &curmailers->next;
9136 continue;
9137 }
9138
9139 Warning("Removing incomplete section 'mailers %s'.\n",
9140 curmailers->id);
9141
9142 m = curmailers->mailer_list;
9143 while (m) {
9144 mb = m->next;
9145 free(m->id);
9146 free(m);
9147 m = mb;
9148 }
9149
9150 /* Destroy and unlink this curmailers section.
9151 * Note: curmailers is backed up into *last.
9152 */
9153 free(curmailers->id);
9154 curmailers = curmailers->next;
9155 free(*last);
9156 *last = curmailers;
9157 }
9158 }
9159
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009160 /* Update server_state_file_name to backend name if backend is supposed to use
9161 * a server-state file locally defined and none has been provided */
9162 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9163 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9164 curproxy->server_state_file_name == NULL)
9165 curproxy->server_state_file_name = strdup(curproxy->id);
9166 }
9167
Willy Tarreau34eb6712011-10-24 18:15:04 +02009168 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009169 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009170 MEM_F_SHARED);
9171
Willy Tarreaubb925012009-07-23 13:36:36 +02009172 if (cfgerr > 0)
9173 err_code |= ERR_ALERT | ERR_FATAL;
9174 out:
9175 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009176}
9177
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009178/*
9179 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9180 * parsing sessions.
9181 */
9182void cfg_register_keywords(struct cfg_kw_list *kwl)
9183{
9184 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9185}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009186
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009187/*
9188 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9189 */
9190void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9191{
9192 LIST_DEL(&kwl->list);
9193 LIST_INIT(&kwl->list);
9194}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009195
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009196/* this function register new section in the haproxy configuration file.
9197 * <section_name> is the name of this new section and <section_parser>
9198 * is the called parser. If two section declaration have the same name,
9199 * only the first declared is used.
9200 */
9201int cfg_register_section(char *section_name,
9202 int (*section_parser)(const char *, int, char **, int))
9203{
9204 struct cfg_section *cs;
9205
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009206 list_for_each_entry(cs, &sections, list) {
9207 if (strcmp(cs->section_name, section_name) == 0) {
9208 Alert("register section '%s': already registered.\n", section_name);
9209 return 0;
9210 }
9211 }
9212
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009213 cs = calloc(1, sizeof(*cs));
9214 if (!cs) {
9215 Alert("register section '%s': out of memory.\n", section_name);
9216 return 0;
9217 }
9218
9219 cs->section_name = section_name;
9220 cs->section_parser = section_parser;
9221
9222 LIST_ADDQ(&sections, &cs->list);
9223
9224 return 1;
9225}
9226
Willy Tarreaubaaee002006-06-26 02:48:02 +02009227/*
David Carlier845efb52015-09-25 11:49:18 +01009228 * free all config section entries
9229 */
9230void cfg_unregister_sections(void)
9231{
9232 struct cfg_section *cs, *ics;
9233
9234 list_for_each_entry_safe(cs, ics, &sections, list) {
9235 LIST_DEL(&cs->list);
9236 free(cs);
9237 }
9238}
9239
Willy Tarreau659fbf02016-05-26 17:55:28 +02009240__attribute__((constructor))
9241static void cfgparse_init(void)
9242{
9243 /* Register internal sections */
9244 cfg_register_section("listen", cfg_parse_listen);
9245 cfg_register_section("frontend", cfg_parse_listen);
9246 cfg_register_section("backend", cfg_parse_listen);
9247 cfg_register_section("defaults", cfg_parse_listen);
9248 cfg_register_section("global", cfg_parse_global);
9249 cfg_register_section("userlist", cfg_parse_users);
9250 cfg_register_section("peers", cfg_parse_peers);
9251 cfg_register_section("mailers", cfg_parse_mailers);
9252 cfg_register_section("namespace_list", cfg_parse_netns);
9253 cfg_register_section("resolvers", cfg_parse_resolvers);
9254}
9255
David Carlier845efb52015-09-25 11:49:18 +01009256/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009257 * Local variables:
9258 * c-indent-level: 8
9259 * c-basic-offset: 8
9260 * End:
9261 */