blob: 261a0ebbe01a22cdcf5a421f56f42ff0611d13c6 [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>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020076#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100205char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int 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 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100241 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200288 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200291 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200298 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100325 * Report an error in <msg> when there are too many arguments. This version is
326 * intended to be used by keyword parsers so that the message will be included
327 * into the general error message. The index is the current keyword in args.
328 * Return 0 if the number of argument is correct, otherwise build a message and
329 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
330 * message may also be null, it will simply not be produced (useful to check only).
331 * <msg> and <err_code> are only affected on error.
332 */
333int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
334{
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 if (msg) {
341 *msg = NULL;
342 memprintf(msg, "%s", args[0]);
343 for (i = 1; i <= index; i++)
344 memprintf(msg, "%s %s", *msg, args[i]);
345
346 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
347 }
348 if (err_code)
349 *err_code |= ERR_ALERT | ERR_FATAL;
350
351 return 1;
352}
353
354/*
355 * same as too_many_args_idx with a 0 index
356 */
357int too_many_args(int maxarg, char **args, char **msg, int *err_code)
358{
359 return too_many_args_idx(maxarg, 0, args, msg, err_code);
360}
361
362/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200363 * Report a fatal Alert when there is too much arguments
364 * The index is the current keyword in args
365 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
366 * Fill err_code with an ERR_ALERT and an ERR_FATAL
367 */
368int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
369{
370 char *kw = NULL;
371 int i;
372
373 if (!*args[index + maxarg + 1])
374 return 0;
375
376 memprintf(&kw, "%s", args[0]);
377 for (i = 1; i <= index; i++) {
378 memprintf(&kw, "%s %s", kw, args[i]);
379 }
380
381 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
382 free(kw);
383 *err_code |= ERR_ALERT | ERR_FATAL;
384 return 1;
385}
386
387/*
388 * same as alertif_too_many_args_idx with a 0 index
389 */
390int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
391{
392 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
393}
394
Willy Tarreau620408f2016-10-21 16:37:51 +0200395/* Report a warning if a rule is placed after a 'tcp-request session' rule.
396 * Return 1 if the warning has been emitted, otherwise 0.
397 */
398int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
399{
400 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
401 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
402 file, line, arg);
403 return 1;
404 }
405 return 0;
406}
407
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200408/* Report a warning if a rule is placed after a 'tcp-request content' rule.
409 * Return 1 if the warning has been emitted, otherwise 0.
410 */
411int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
412{
413 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
414 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
415 file, line, arg);
416 return 1;
417 }
418 return 0;
419}
420
Willy Tarreau61d18892009-03-31 10:49:21 +0200421/* Report a warning if a rule is placed after a 'block' rule.
422 * Return 1 if the warning has been emitted, otherwise 0.
423 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100424int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200425{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200426 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200427 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
428 file, line, arg);
429 return 1;
430 }
431 return 0;
432}
433
Willy Tarreau5002f572014-04-23 01:32:02 +0200434/* Report a warning if a rule is placed after an 'http_request' rule.
435 * Return 1 if the warning has been emitted, otherwise 0.
436 */
437int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
438{
439 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
440 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
441 file, line, arg);
442 return 1;
443 }
444 return 0;
445}
446
Willy Tarreau61d18892009-03-31 10:49:21 +0200447/* Report a warning if a rule is placed after a reqrewrite rule.
448 * Return 1 if the warning has been emitted, otherwise 0.
449 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
452 if (proxy->req_exp) {
453 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
454 file, line, arg);
455 return 1;
456 }
457 return 0;
458}
459
460/* Report a warning if a rule is placed after a reqadd rule.
461 * Return 1 if the warning has been emitted, otherwise 0.
462 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100463int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200464{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100465 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
467 file, line, arg);
468 return 1;
469 }
470 return 0;
471}
472
473/* Report a warning if a rule is placed after a redirect rule.
474 * Return 1 if the warning has been emitted, otherwise 0.
475 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
479 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
480 file, line, arg);
481 return 1;
482 }
483 return 0;
484}
485
486/* Report a warning if a rule is placed after a 'use_backend' rule.
487 * Return 1 if the warning has been emitted, otherwise 0.
488 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
491 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
492 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
493 file, line, arg);
494 return 1;
495 }
496 return 0;
497}
498
Willy Tarreauee445d92014-04-23 01:39:04 +0200499/* Report a warning if a rule is placed after a 'use-server' rule.
500 * Return 1 if the warning has been emitted, otherwise 0.
501 */
502int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
503{
504 if (!LIST_ISEMPTY(&proxy->server_rules)) {
505 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
506 file, line, arg);
507 return 1;
508 }
509 return 0;
510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a redirect rule is dangerously placed */
513int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200516 warnif_rule_after_use_server(proxy, file, line, arg);
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a reqadd rule is dangerously placed */
520int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_redirect(proxy, file, line, arg) ||
523 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqxxx rule is dangerously placed */
527int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
530 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200531}
532
533/* report a warning if an http-request rule is dangerously placed */
534int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
535{
Willy Tarreau61d18892009-03-31 10:49:21 +0200536 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100537 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a block rule is dangerously placed */
541int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_http_req(proxy, file, line, arg) ||
544 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a "tcp request content" rule is dangerously placed */
548int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_block(proxy, file, line, arg) ||
551 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request session" rule is dangerously placed */
555int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
558 warnif_misplaced_tcp_cont(proxy, file, line, arg);
559}
560
561/* report a warning if a "tcp request connection" rule is dangerously placed */
562int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
563{
564 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200566}
567
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568/* Report it if a request ACL condition uses some keywords that are incompatible
569 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
570 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
571 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 return 0;
580
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 acl = acl_cond_conflicts(cond, where);
582 if (acl) {
583 if (acl->name && *acl->name)
584 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
585 file, line, acl->name, sample_ckp_names(where));
586 else
587 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 +0200588 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 return ERR_WARN;
590 }
591 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100592 return 0;
593
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 if (acl->name && *acl->name)
595 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200596 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100597 else
598 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200599 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100600 return ERR_WARN;
601}
602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 * parse a line in a <global> section. Returns the error code, 0 if OK, or
605 * any combination of :
606 * - ERR_ABORT: must abort ASAP
607 * - ERR_FATAL: we can continue parsing but not start the service
608 * - ERR_WARN: a warning has been emitted
609 * - ERR_ALERT: an alert has been emitted
610 * Only the two first ones can stop processing, the two others are just
611 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200613int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614{
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200616 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
618 if (!strcmp(args[0], "global")) { /* new section */
619 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200620 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200624 if (alertif_too_many_args(0, file, linenum, args, &err_code))
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 global.mode |= MODE_DAEMON;
627 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200628 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200631 if (*args[1]) {
632 if (!strcmp(args[1], "exit-on-failure")) {
633 global.tune.options |= GTUNE_EXIT_ONFAILURE;
634 } else {
635 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
638 }
639 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200640 global.mode |= MODE_MWORKER;
641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 global.mode |= MODE_DEBUG;
646 }
647 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100660 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100665 global.tune.options &= ~GTUNE_USE_SPLICE;
666 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200670 global.tune.options &= ~GTUNE_USE_GAI;
671 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000672 else if (!strcmp(args[0], "noreuseport")) {
673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
675 global.tune.options &= ~GTUNE_USE_REUSEPORT;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_QUIET;
681 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 if (global.tune.maxpollevents != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200694 }
695 global.tune.maxpollevents = atol(args[1]);
696 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 if (global.tune.maxaccept != 0) {
701 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100709 }
710 global.tune.maxaccept = atol(args[1]);
711 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.chksize = atol(args[1]);
721 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100722 else if (!strcmp(args[0], "tune.recv_enough")) {
723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.recv_enough = atol(args[1]);
731 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.buf_limit = atol(args[1]);
741 if (global.tune.buf_limit) {
742 if (global.tune.buf_limit < 3)
743 global.tune.buf_limit = 3;
744 if (global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
746 }
747 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100748 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.reserved_bufs = atol(args[1]);
757 if (global.tune.reserved_bufs < 2)
758 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100759 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
760 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200771 if (global.tune.bufsize <= 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100776 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100777 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
779 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200788 if (global.tune.maxrewrite < 0) {
789 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200793 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100794 else if (!strcmp(args[0], "tune.idletimer")) {
795 unsigned int idle;
796 const char *res;
797
William Lallemand1a748ae2015-05-19 16:37:23 +0200798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
799 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805
806 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
807 if (res) {
808 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
809 file, linenum, *res, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813
814 if (idle > 65535) {
815 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.idle_timer = idle;
820 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.client_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.client_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.server_rcvbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.server_rcvbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.client_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.client_sndbuf = atol(args[1]);
865 }
866 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100869 if (global.tune.server_sndbuf != 0) {
870 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT;
872 goto out;
873 }
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.server_sndbuf = atol(args[1]);
880 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200881 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.pipesize = atol(args[1]);
890 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100891 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.cookie_len = atol(args[1]) + 1;
900 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200901 else if (!strcmp(args[0], "tune.http.logurilen")) {
902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.requri_len = atol(args[1]) + 1;
910 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200911 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 global.tune.max_http_hdr = atol(args[1]);
920 }
William Lallemandf3747832012-11-09 12:33:10 +0100921 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200922 if (alertif_too_many_args(1, file, linenum, args, &err_code))
923 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100924 if (*args[1]) {
925 global.tune.comp_maxlevel = atoi(args[1]);
926 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
927 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
928 file, linenum, args[0]);
929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
931 }
932 } else {
933 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200939 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
940 if (*args[1]) {
941 global.tune.pattern_cache = atoi(args[1]);
942 if (global.tune.pattern_cache < 0) {
943 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
944 file, linenum, args[0]);
945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
947 }
948 } else {
949 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
950 file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200959 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100968 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
969 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]);
970 err_code |= ERR_WARN;
971 goto out;
972 }
973
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 }
975 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200976 if (alertif_too_many_args(1, file, linenum, args, &err_code))
977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200980 err_code |= ERR_ALERT;
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100988 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
989 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]);
990 err_code |= ERR_WARN;
991 goto out;
992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
Simon Horman98637e52014-06-20 12:30:16 +0900994 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200995 if (alertif_too_many_args(0, file, linenum, args, &err_code))
996 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900997 global.external_check = 1;
998 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200999 /* user/group name handling */
1000 else if (!strcmp(args[0], "user")) {
1001 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001002 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1003 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001004 if (global.uid != 0) {
1005 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_ALERT;
1007 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001008 }
1009 errno = 0;
1010 ha_user = getpwnam(args[1]);
1011 if (ha_user != NULL) {
1012 global.uid = (int)ha_user->pw_uid;
1013 }
1014 else {
1015 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 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001017 }
1018 }
1019 else if (!strcmp(args[0], "group")) {
1020 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001021 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1022 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001023 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001024 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001025 err_code |= ERR_ALERT;
1026 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001027 }
1028 errno = 0;
1029 ha_group = getgrnam(args[1]);
1030 if (ha_group != NULL) {
1031 global.gid = (int)ha_group->gr_gid;
1032 }
1033 else {
1034 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 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001036 }
1037 }
1038 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 }
1047 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001048 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1049 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1050 file, linenum, args[0], LONGBITS, global.nbproc);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001056 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 if (global.maxconn != 0) {
1059 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001060 err_code |= ERR_ALERT;
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
1063 if (*(args[1]) == 0) {
1064 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 }
1068 global.maxconn = atol(args[1]);
1069#ifdef SYSTEM_MAXCONN
1070 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1071 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);
1072 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001073 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
1075#endif /* SYSTEM_MAXCONN */
1076 }
Emeric Brun850efd52014-01-29 12:24:34 +01001077 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001078 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1079 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 if (strcmp(args[1],"none") == 0)
1086 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1087 else if (strcmp(args[1],"required") == 0)
1088 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1089 else {
1090 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1091 err_code |= ERR_ALERT | ERR_FATAL;
1092 goto out;
1093 }
1094 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001095 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001096 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1097 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001098 if (global.cps_lim != 0) {
1099 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1100 err_code |= ERR_ALERT;
1101 goto out;
1102 }
1103 if (*(args[1]) == 0) {
1104 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto out;
1107 }
1108 global.cps_lim = atol(args[1]);
1109 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001110 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001111 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1112 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001113 if (global.sps_lim != 0) {
1114 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT;
1116 goto out;
1117 }
1118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.sps_lim = atol(args[1]);
1124 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001125 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001126 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1127 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001128 if (global.ssl_lim != 0) {
1129 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1130 err_code |= ERR_ALERT;
1131 goto out;
1132 }
1133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
1137 }
1138 global.ssl_lim = atol(args[1]);
1139 }
William Lallemandd85f9172012-11-09 17:05:39 +01001140 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148 global.comp_rate_lim = atoi(args[1]) * 1024;
1149 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001150 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1152 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001153 if (global.maxpipes != 0) {
1154 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT;
1156 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001157 }
1158 if (*(args[1]) == 0) {
1159 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001162 }
1163 global.maxpipes = atol(args[1]);
1164 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001165 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001166 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1167 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001168 if (*(args[1]) == 0) {
1169 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172 }
William Lallemande3a7d992012-11-20 11:25:20 +01001173 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001174 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001175 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001176 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1177 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001178 if (*(args[1]) == 0) {
1179 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
1182 }
1183 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001184 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001185 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001189 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001190
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001192 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 if (global.rlimit_nofile != 0) {
1195 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 if (*(args[1]) == 0) {
1200 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 global.rlimit_nofile = atol(args[1]);
1205 }
1206 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001207 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 if (global.chroot != NULL) {
1210 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT;
1212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
1214 if (*(args[1]) == 0) {
1215 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 }
1219 global.chroot = strdup(args[1]);
1220 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001221 else if (!strcmp(args[0], "description")) {
1222 int i, len=0;
1223 char *d;
1224
1225 if (!*args[1]) {
1226 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1227 file, linenum, args[0]);
1228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
1230 }
1231
Willy Tarreau348acfe2014-04-14 15:00:39 +02001232 for (i = 1; *args[i]; i++)
1233 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001234
1235 if (global.desc)
1236 free(global.desc);
1237
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001238 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001239
Willy Tarreau348acfe2014-04-14 15:00:39 +02001240 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1241 for (i = 2; *args[i]; i++)
1242 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001243 }
1244 else if (!strcmp(args[0], "node")) {
1245 int i;
1246 char c;
1247
William Lallemand1a748ae2015-05-19 16:37:23 +02001248 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1249 goto out;
1250
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001251 for (i=0; args[1][i]; i++) {
1252 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001253 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1254 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001255 break;
1256 }
1257
1258 if (!i || args[1][i]) {
1259 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1260 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1261 file, linenum, args[0]);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
1264 }
1265
1266 if (global.node)
1267 free(global.node);
1268
1269 global.node = strdup(args[1]);
1270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (global.pidfile != NULL) {
1275 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001276 err_code |= ERR_ALERT;
1277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 }
1279 if (*(args[1]) == 0) {
1280 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 }
1284 global.pidfile = strdup(args[1]);
1285 }
Emeric Bruned760922010-10-22 17:59:25 +02001286 else if (!strcmp(args[0], "unix-bind")) {
1287 int cur_arg = 1;
1288 while (*(args[cur_arg])) {
1289 if (!strcmp(args[cur_arg], "prefix")) {
1290 if (global.unix_bind.prefix != NULL) {
1291 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1292 err_code |= ERR_ALERT;
1293 cur_arg += 2;
1294 continue;
1295 }
1296
1297 if (*(args[cur_arg+1]) == 0) {
1298 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1303 cur_arg += 2;
1304 continue;
1305 }
1306
1307 if (!strcmp(args[cur_arg], "mode")) {
1308
1309 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1310 cur_arg += 2;
1311 continue;
1312 }
1313
1314 if (!strcmp(args[cur_arg], "uid")) {
1315
1316 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1317 cur_arg += 2;
1318 continue;
1319 }
1320
1321 if (!strcmp(args[cur_arg], "gid")) {
1322
1323 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1324 cur_arg += 2;
1325 continue;
1326 }
1327
1328 if (!strcmp(args[cur_arg], "user")) {
1329 struct passwd *user;
1330
1331 user = getpwnam(args[cur_arg + 1]);
1332 if (!user) {
1333 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1334 file, linenum, args[0], args[cur_arg + 1 ]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338
1339 global.unix_bind.ux.uid = user->pw_uid;
1340 cur_arg += 2;
1341 continue;
1342 }
1343
1344 if (!strcmp(args[cur_arg], "group")) {
1345 struct group *group;
1346
1347 group = getgrnam(args[cur_arg + 1]);
1348 if (!group) {
1349 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1350 file, linenum, args[0], args[cur_arg + 1 ]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354
1355 global.unix_bind.ux.gid = group->gr_gid;
1356 cur_arg += 2;
1357 continue;
1358 }
1359
Willy Tarreaub48f9582011-09-05 01:17:06 +02001360 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001361 file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
1365 }
William Lallemand0f99e342011-10-12 17:50:54 +02001366 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1367 /* delete previous herited or defined syslog servers */
1368 struct logsrv *back;
1369 struct logsrv *tmp;
1370
1371 if (*(args[1]) != 0) {
1372 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1373 err_code |= ERR_ALERT | ERR_FATAL;
1374 goto out;
1375 }
1376
1377 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1378 LIST_DEL(&tmp->list);
1379 free(tmp);
1380 }
1381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001383 struct sockaddr_storage *sk;
1384 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001385 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001386 int arg = 0;
1387 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001388
William Lallemand1a748ae2015-05-19 16:37:23 +02001389 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1390 goto out;
1391
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 if (*(args[1]) == 0 || *(args[2]) == 0) {
1393 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 }
William Lallemand0f99e342011-10-12 17:50:54 +02001397
Vincent Bernat02779b62016-04-03 13:48:43 +02001398 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001399
Willy Tarreau18324f52014-06-27 18:10:07 +02001400 /* just after the address, a length may be specified */
1401 if (strcmp(args[arg+2], "len") == 0) {
1402 len = atoi(args[arg+3]);
1403 if (len < 80 || len > 65535) {
1404 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1405 file, linenum, args[arg+3]);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto out;
1408 }
1409 logsrv->maxlen = len;
1410
1411 /* skip these two args */
1412 arg += 2;
1413 }
1414 else
1415 logsrv->maxlen = MAX_SYSLOG_LEN;
1416
1417 if (logsrv->maxlen > global.max_syslog_len) {
1418 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001419 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1420 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1421 logline = my_realloc2(logline, global.max_syslog_len + 1);
1422 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001423 }
1424
Dragan Dosen1322d092015-09-22 16:05:32 +02001425 /* after the length, a format may be specified */
1426 if (strcmp(args[arg+2], "format") == 0) {
1427 logsrv->format = get_log_format(args[arg+3]);
1428 if (logsrv->format < 0) {
1429 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001431 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001432 goto out;
1433 }
1434
1435 /* skip these two args */
1436 arg += 2;
1437 }
1438
David Carlier97880bb2016-04-08 10:35:26 +01001439 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1440 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001441 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001442 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001443
Willy Tarreau18324f52014-06-27 18:10:07 +02001444 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001445 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001446 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001447 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001448 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
1450
William Lallemand0f99e342011-10-12 17:50:54 +02001451 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001452 if (*(args[arg+3])) {
1453 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001454 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001455 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001456 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 }
1459 }
1460
William Lallemand0f99e342011-10-12 17:50:54 +02001461 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001462 if (*(args[arg+4])) {
1463 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001464 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001465 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001467 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001468 }
1469 }
1470
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001471 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001472 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001473 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001474 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001475 free(logsrv);
1476 goto out;
1477 }
1478 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001479
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001480 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001481 if (port1 != port2) {
1482 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1483 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001484 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001485 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001486 goto out;
1487 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001488
William Lallemand0f99e342011-10-12 17:50:54 +02001489 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001490 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001491 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
William Lallemand0f99e342011-10-12 17:50:54 +02001494 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001495 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001496 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1497 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001498
1499 if (global.log_send_hostname != NULL) {
1500 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1501 err_code |= ERR_ALERT;
1502 goto out;
1503 }
1504
1505 if (*(args[1]))
1506 name = args[1];
1507 else
1508 name = hostname;
1509
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001510 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001511 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001512 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001513 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1514 if (global.server_state_base != NULL) {
1515 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1516 err_code |= ERR_ALERT;
1517 goto out;
1518 }
1519
1520 if (!*(args[1])) {
1521 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1522 err_code |= ERR_FATAL;
1523 goto out;
1524 }
1525
1526 global.server_state_base = strdup(args[1]);
1527 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001528 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1529 if (global.server_state_file != NULL) {
1530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1531 err_code |= ERR_ALERT;
1532 goto out;
1533 }
1534
1535 if (!*(args[1])) {
1536 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1537 err_code |= ERR_FATAL;
1538 goto out;
1539 }
1540
1541 global.server_state_file = strdup(args[1]);
1542 }
Kevinm48936af2010-12-22 16:08:21 +00001543 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001544 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1545 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001546 if (*(args[1]) == 0) {
1547 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
1550 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001551 chunk_destroy(&global.log_tag);
1552 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001553 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001554 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001555 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1556 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001557 if (global.spread_checks != 0) {
1558 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT;
1560 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001561 }
1562 if (*(args[1]) == 0) {
1563 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001566 }
1567 global.spread_checks = atol(args[1]);
1568 if (global.spread_checks < 0 || global.spread_checks > 50) {
1569 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001573 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1574 const char *err;
1575 unsigned int val;
1576
William Lallemand1a748ae2015-05-19 16:37:23 +02001577 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1578 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001579 if (*(args[1]) == 0) {
1580 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1581 err_code |= ERR_ALERT | ERR_FATAL;
1582 goto out;
1583 }
1584
1585 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1586 if (err) {
1587 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1588 err_code |= ERR_ALERT | ERR_FATAL;
1589 }
1590 global.max_spread_checks = val;
1591 if (global.max_spread_checks < 0) {
1592 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1593 err_code |= ERR_ALERT | ERR_FATAL;
1594 }
1595 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001596 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1597#ifdef USE_CPU_AFFINITY
1598 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001599 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001600 unsigned long cpus = 0;
1601
1602 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001603 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001604 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001605 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001607 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001608 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = atol(args[1]);
1610 if (proc >= 1 && proc <= LONGBITS)
1611 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 }
1613
1614 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 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",
1616 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
1619 }
1620
1621 cur_arg = 2;
1622 while (*args[cur_arg]) {
1623 unsigned int low, high;
1624
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001625 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001626 char *dash = strchr(args[cur_arg], '-');
1627
1628 low = high = str2uic(args[cur_arg]);
1629 if (dash)
1630 high = str2uic(dash + 1);
1631
1632 if (high < low) {
1633 unsigned int swap = low;
1634 low = high;
1635 high = swap;
1636 }
1637
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001638 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001639 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001640 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
1643 }
1644
1645 while (low <= high)
1646 cpus |= 1UL << low++;
1647 }
1648 else {
1649 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1650 file, linenum, args[0], args[cur_arg]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654 cur_arg++;
1655 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001656 for (i = 0; i < LONGBITS; i++)
1657 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001658 global.cpu_map[i] = cpus;
1659#else
1660 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
1663#endif
1664 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001665 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1666 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1667 goto out;
1668
1669 if (*(args[2]) == 0) {
1670 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
1673 }
1674
1675 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1676 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1677 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
1680 }
1681 }
1682 else if (!strcmp(args[0], "unsetenv")) {
1683 int arg;
1684
1685 if (*(args[1]) == 0) {
1686 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
1689 }
1690
1691 for (arg = 1; *args[arg]; arg++) {
1692 if (unsetenv(args[arg]) != 0) {
1693 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
1696 }
1697 }
1698 }
1699 else if (!strcmp(args[0], "resetenv")) {
1700 extern char **environ;
1701 char **env = environ;
1702
1703 /* args contain variable names to keep, one per argument */
1704 while (*env) {
1705 int arg;
1706
1707 /* look for current variable in among all those we want to keep */
1708 for (arg = 1; *args[arg]; arg++) {
1709 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1710 (*env)[strlen(args[arg])] == '=')
1711 break;
1712 }
1713
1714 /* delete this variable */
1715 if (!*args[arg]) {
1716 char *delim = strchr(*env, '=');
1717
1718 if (!delim || delim - *env >= trash.size) {
1719 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
1724 memcpy(trash.str, *env, delim - *env);
1725 trash.str[delim - *env] = 0;
1726
1727 if (unsetenv(trash.str) != 0) {
1728 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
1731 }
1732 }
1733 else
1734 env++;
1735 }
1736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001738 struct cfg_kw_list *kwl;
1739 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001740 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001741
1742 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1743 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1744 if (kwl->kw[index].section != CFG_GLOBAL)
1745 continue;
1746 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001747 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001748 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001749 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001751 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001752 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001753 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001754 err_code |= ERR_WARN;
1755 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001756 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001757 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001758 }
1759 }
1760 }
1761
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001765
Willy Tarreau058e9072009-07-20 09:30:05 +02001766 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001767 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001768 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769}
1770
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001771void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001773 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 defproxy.mode = PR_MODE_TCP;
1775 defproxy.state = PR_STNEW;
1776 defproxy.maxconn = cfg_maxpconn;
1777 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001778 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001779 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001780
Simon Horman66183002013-02-23 10:16:43 +09001781 defproxy.defsrv.check.inter = DEF_CHKINTR;
1782 defproxy.defsrv.check.fastinter = 0;
1783 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001784 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1785 defproxy.defsrv.agent.fastinter = 0;
1786 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001787 defproxy.defsrv.check.rise = DEF_RISETIME;
1788 defproxy.defsrv.check.fall = DEF_FALLTIME;
1789 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1790 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001791 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001792 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001793 defproxy.defsrv.maxqueue = 0;
1794 defproxy.defsrv.minconn = 0;
1795 defproxy.defsrv.maxconn = 0;
1796 defproxy.defsrv.slowstart = 0;
1797 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1798 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1799 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001800
1801 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001802 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803}
1804
Willy Tarreauade5ec42010-01-28 19:33:49 +01001805
Willy Tarreau63af98d2014-05-18 08:11:41 +02001806/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1807 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1808 * ERR_FATAL in case of error.
1809 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001810static int create_cond_regex_rule(const char *file, int line,
1811 struct proxy *px, int dir, int action, int flags,
1812 const char *cmd, const char *reg, const char *repl,
1813 const char **cond_start)
1814{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001815 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001816 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001817 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001818 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001819 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001820 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 int cs;
1822 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823
1824 if (px == &defproxy) {
1825 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001826 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001827 goto err;
1828 }
1829
1830 if (*reg == 0) {
1831 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833 goto err;
1834 }
1835
Christopher Faulet898566e2016-10-26 11:06:28 +02001836 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001837 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001838
Willy Tarreau5321c422010-01-28 20:35:13 +01001839 if (cond_start &&
1840 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001841 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1842 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1843 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001844 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001845 goto err;
1846 }
1847 }
1848 else if (cond_start && **cond_start) {
1849 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1850 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001851 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001852 goto err;
1853 }
1854
Willy Tarreau63af98d2014-05-18 08:11:41 +02001855 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001856 (dir == SMP_OPT_DIR_REQ) ?
1857 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1858 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1859 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001860
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001861 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001862 if (!preg) {
1863 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001864 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001865 goto err;
1866 }
1867
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001868 cs = !(flags & REG_ICASE);
1869 cap = !(flags & REG_NOSUB);
1870 error = NULL;
1871 if (!regex_comp(reg, preg, cs, cap, &error)) {
1872 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1873 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001874 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001875 goto err;
1876 }
1877
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001878 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001879 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001880 if (repl && err) {
1881 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1882 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001883 ret_code |= ERR_ALERT | ERR_FATAL;
1884 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001885 }
1886
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001887 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001888 ret_code |= ERR_WARN;
1889
1890 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891
Willy Tarreau63af98d2014-05-18 08:11:41 +02001892 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001893 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001894 err:
1895 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001896 free(errmsg);
1897 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001898}
1899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900/*
William Lallemand51097192015-04-14 16:35:22 +02001901 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001902 * Returns the error code, 0 if OK, or any combination of :
1903 * - ERR_ABORT: must abort ASAP
1904 * - ERR_FATAL: we can continue parsing but not start the service
1905 * - ERR_WARN: a warning has been emitted
1906 * - ERR_ALERT: an alert has been emitted
1907 * Only the two first ones can stop processing, the two others are just
1908 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001910int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1911{
1912 static struct peers *curpeers = NULL;
1913 struct peer *newpeer = NULL;
1914 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001915 struct bind_conf *bind_conf;
1916 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001917 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001918 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001919
1920 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001921 if (!*args[1]) {
1922 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001923 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001924 goto out;
1925 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001926
William Lallemand6e62fb62015-04-28 16:55:23 +02001927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1928 goto out;
1929
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 err = invalid_char(args[1]);
1931 if (err) {
1932 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1933 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001934 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001935 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001936 }
1937
1938 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1939 /*
1940 * If there are two proxies with the same name only following
1941 * combinations are allowed:
1942 */
1943 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001944 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 +02001945 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001947 }
1948 }
1949
Vincent Bernat02779b62016-04-03 13:48:43 +02001950 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001951 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1952 err_code |= ERR_ALERT | ERR_ABORT;
1953 goto out;
1954 }
1955
1956 curpeers->next = peers;
1957 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001958 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001959 curpeers->conf.line = linenum;
1960 curpeers->last_change = now.tv_sec;
1961 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001962 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001963 }
1964 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001965 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001966 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001967 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001968
1969 if (!*args[2]) {
1970 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1971 file, linenum, args[0]);
1972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
1974 }
1975
1976 err = invalid_char(args[1]);
1977 if (err) {
1978 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1979 file, linenum, *err, args[1]);
1980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
1983
Vincent Bernat02779b62016-04-03 13:48:43 +02001984 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001985 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1986 err_code |= ERR_ALERT | ERR_ABORT;
1987 goto out;
1988 }
1989
1990 /* the peers are linked backwards first */
1991 curpeers->count++;
1992 newpeer->next = curpeers->remote;
1993 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001994 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001995 newpeer->conf.line = linenum;
1996
1997 newpeer->last_change = now.tv_sec;
1998 newpeer->id = strdup(args[1]);
1999
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002000 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002001 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002002 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002005 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002006
2007 proto = protocol_by_family(sk->ss_family);
2008 if (!proto || !proto->connect) {
2009 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2010 file, linenum, args[0], args[1]);
2011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
2013 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002014
2015 if (port1 != port2) {
2016 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2017 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
2020 }
2021
Willy Tarreau2aa38802013-02-20 19:20:59 +01002022 if (!port1) {
2023 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2024 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
2026 goto out;
2027 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028
Emeric Brun32da3c42010-09-23 18:39:19 +02002029 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002030 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002031 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002032 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002033
Emeric Brun32da3c42010-09-23 18:39:19 +02002034 if (strcmp(newpeer->id, localpeer) == 0) {
2035 /* Current is local peer, it define a frontend */
2036 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002037 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002038
2039 if (!curpeers->peers_fe) {
2040 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2041 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2042 err_code |= ERR_ALERT | ERR_ABORT;
2043 goto out;
2044 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002045
Willy Tarreau237250c2011-07-29 01:49:03 +02002046 init_new_proxy(curpeers->peers_fe);
2047 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002048 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002049 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2050 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002051 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002052
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002053 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002054
Willy Tarreau902636f2013-03-10 19:44:48 +01002055 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2056 if (errmsg && *errmsg) {
2057 indent_msg(&errmsg, 2);
2058 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002059 }
2060 else
2061 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2062 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002063 err_code |= ERR_FATAL;
2064 goto out;
2065 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002066
2067 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002068 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002069 l->maxconn = curpeers->peers_fe->maxconn;
2070 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002071 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002072 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002073 l->analysers |= curpeers->peers_fe->fe_req_ana;
2074 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002075 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2076 global.maxsock += l->maxconn;
2077 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002078 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002079 else {
2080 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2081 file, linenum, args[0], args[1],
2082 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2083 err_code |= ERR_FATAL;
2084 goto out;
2085 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002086 }
2087 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002088 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2089 curpeers->state = PR_STSTOPPED;
2090 }
2091 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2092 curpeers->state = PR_STNEW;
2093 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002094 else if (*args[0] != 0) {
2095 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
2099
2100out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002101 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002102 return err_code;
2103}
2104
Baptiste Assmann325137d2015-04-13 23:40:55 +02002105/*
2106 * Parse a <resolvers> section.
2107 * Returns the error code, 0 if OK, or any combination of :
2108 * - ERR_ABORT: must abort ASAP
2109 * - ERR_FATAL: we can continue parsing but not start the service
2110 * - ERR_WARN: a warning has been emitted
2111 * - ERR_ALERT: an alert has been emitted
2112 * Only the two first ones can stop processing, the two others are just
2113 * indicators.
2114 */
2115int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2116{
2117 static struct dns_resolvers *curr_resolvers = NULL;
2118 struct dns_nameserver *newnameserver = NULL;
2119 const char *err;
2120 int err_code = 0;
2121 char *errmsg = NULL;
2122
2123 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2124 if (!*args[1]) {
2125 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2126 err_code |= ERR_ALERT | ERR_ABORT;
2127 goto out;
2128 }
2129
2130 err = invalid_char(args[1]);
2131 if (err) {
2132 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2133 file, linenum, *err, args[0], args[1]);
2134 err_code |= ERR_ALERT | ERR_ABORT;
2135 goto out;
2136 }
2137
2138 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2139 /* Error if two resolvers owns the same name */
2140 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2141 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2142 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2143 err_code |= ERR_ALERT | ERR_ABORT;
2144 }
2145 }
2146
Vincent Bernat02779b62016-04-03 13:48:43 +02002147 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 goto out;
2151 }
2152
2153 /* default values */
2154 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2155 curr_resolvers->conf.file = strdup(file);
2156 curr_resolvers->conf.line = linenum;
2157 curr_resolvers->id = strdup(args[1]);
2158 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002159 /* default hold period for nx, other, refuse and timeout is 30s */
2160 curr_resolvers->hold.nx = 30000;
2161 curr_resolvers->hold.other = 30000;
2162 curr_resolvers->hold.refused = 30000;
2163 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002164 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002165 curr_resolvers->hold.valid = 10000;
2166 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002167 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002168 /* default resolution pool size */
2169 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002170 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002171 LIST_INIT(&curr_resolvers->resolution.curr);
2172 LIST_INIT(&curr_resolvers->resolution.wait);
2173 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002174 }
2175 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2176 struct sockaddr_storage *sk;
2177 int port1, port2;
2178 struct protocol *proto;
2179
2180 if (!*args[2]) {
2181 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2182 file, linenum, args[0]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186
2187 err = invalid_char(args[1]);
2188 if (err) {
2189 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2190 file, linenum, *err, args[1]);
2191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
2193 }
2194
Baptiste Assmanna315c552015-11-02 22:55:49 +01002195 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2196 /* Error if two resolvers owns the same name */
2197 if (strcmp(newnameserver->id, args[1]) == 0) {
2198 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2199 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 }
2202 }
2203
Vincent Bernat02779b62016-04-03 13:48:43 +02002204 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
2208 }
2209
2210 /* the nameservers are linked backward first */
2211 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2212 curr_resolvers->count_nameservers++;
2213 newnameserver->resolvers = curr_resolvers;
2214 newnameserver->conf.file = strdup(file);
2215 newnameserver->conf.line = linenum;
2216 newnameserver->id = strdup(args[1]);
2217
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002218 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002219 if (!sk) {
2220 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
2225 proto = protocol_by_family(sk->ss_family);
2226 if (!proto || !proto->connect) {
2227 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2228 file, linenum, args[0], args[1]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232
2233 if (port1 != port2) {
2234 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2235 file, linenum, args[0], args[1], args[2]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002240 if (!port1 && !port2) {
2241 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2242 file, linenum, args[0], args[1]);
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246
Baptiste Assmann325137d2015-04-13 23:40:55 +02002247 newnameserver->addr = *sk;
2248 }
2249 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2250 const char *res;
2251 unsigned int time;
2252
2253 if (!*args[2]) {
2254 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2255 file, linenum, args[0]);
2256 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2261 if (res) {
2262 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2263 file, linenum, *res, args[0]);
2264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
2266 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002267 if (strcmp(args[1], "nx") == 0)
2268 curr_resolvers->hold.nx = time;
2269 else if (strcmp(args[1], "other") == 0)
2270 curr_resolvers->hold.other = time;
2271 else if (strcmp(args[1], "refused") == 0)
2272 curr_resolvers->hold.refused = time;
2273 else if (strcmp(args[1], "timeout") == 0)
2274 curr_resolvers->hold.timeout = time;
2275 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002276 curr_resolvers->hold.valid = time;
2277 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002278 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2279 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002285 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2286 if (!*args[1]) {
2287 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2288 file, linenum, args[0]);
2289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
2291 }
2292 curr_resolvers->resolution_pool_size = atoi(args[1]);
2293 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002294 else if (strcmp(args[0], "resolve_retries") == 0) {
2295 if (!*args[1]) {
2296 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2297 file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301 curr_resolvers->resolve_retries = atoi(args[1]);
2302 }
2303 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002304 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002305 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2306 file, linenum, args[0]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002310 else if (strcmp(args[1], "retry") == 0) {
2311 const char *res;
2312 unsigned int timeout_retry;
2313
2314 if (!*args[2]) {
2315 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2316 file, linenum, args[0], args[1]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2321 if (res) {
2322 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2323 file, linenum, *res, args[0], args[1]);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327 curr_resolvers->timeout.retry = timeout_retry;
2328 }
2329 else {
2330 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2331 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002335 } /* neither "nameserver" nor "resolvers" */
2336 else if (*args[0] != 0) {
2337 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
2341
2342 out:
2343 free(errmsg);
2344 return err_code;
2345}
Simon Horman0d16a402015-01-30 11:22:58 +09002346
2347/*
William Lallemand51097192015-04-14 16:35:22 +02002348 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002349 * Returns the error code, 0 if OK, or any combination of :
2350 * - ERR_ABORT: must abort ASAP
2351 * - ERR_FATAL: we can continue parsing but not start the service
2352 * - ERR_WARN: a warning has been emitted
2353 * - ERR_ALERT: an alert has been emitted
2354 * Only the two first ones can stop processing, the two others are just
2355 * indicators.
2356 */
2357int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2358{
2359 static struct mailers *curmailers = NULL;
2360 struct mailer *newmailer = NULL;
2361 const char *err;
2362 int err_code = 0;
2363 char *errmsg = NULL;
2364
2365 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2366 if (!*args[1]) {
2367 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2368 err_code |= ERR_ALERT | ERR_ABORT;
2369 goto out;
2370 }
2371
2372 err = invalid_char(args[1]);
2373 if (err) {
2374 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2375 file, linenum, *err, args[0], args[1]);
2376 err_code |= ERR_ALERT | ERR_ABORT;
2377 goto out;
2378 }
2379
2380 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2381 /*
2382 * If there are two proxies with the same name only following
2383 * combinations are allowed:
2384 */
2385 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002386 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 +09002387 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002389 }
2390 }
2391
Vincent Bernat02779b62016-04-03 13:48:43 +02002392 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002393 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2394 err_code |= ERR_ALERT | ERR_ABORT;
2395 goto out;
2396 }
2397
2398 curmailers->next = mailers;
2399 mailers = curmailers;
2400 curmailers->conf.file = strdup(file);
2401 curmailers->conf.line = linenum;
2402 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002403 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2404 * But need enough time so that timeouts don't occur
2405 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002406 }
2407 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2408 struct sockaddr_storage *sk;
2409 int port1, port2;
2410 struct protocol *proto;
2411
2412 if (!*args[2]) {
2413 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2414 file, linenum, args[0]);
2415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
2417 }
2418
2419 err = invalid_char(args[1]);
2420 if (err) {
2421 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2422 file, linenum, *err, args[1]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
Vincent Bernat02779b62016-04-03 13:48:43 +02002427 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2429 err_code |= ERR_ALERT | ERR_ABORT;
2430 goto out;
2431 }
2432
2433 /* the mailers are linked backwards first */
2434 curmailers->count++;
2435 newmailer->next = curmailers->mailer_list;
2436 curmailers->mailer_list = newmailer;
2437 newmailer->mailers = curmailers;
2438 newmailer->conf.file = strdup(file);
2439 newmailer->conf.line = linenum;
2440
2441 newmailer->id = strdup(args[1]);
2442
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002443 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002444 if (!sk) {
2445 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
2450 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002451 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2452 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002453 file, linenum, args[0], args[1]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 if (port1 != port2) {
2459 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2460 file, linenum, args[0], args[1], args[2]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465 if (!port1) {
2466 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2467 file, linenum, args[0], args[1], args[2]);
2468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
2470 }
2471
2472 newmailer->addr = *sk;
2473 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002474 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002475 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002476 }
2477 else if (strcmp(args[0], "timeout") == 0) {
2478 if (!*args[1]) {
2479 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2480 file, linenum, args[0]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484 else if (strcmp(args[1], "mail") == 0) {
2485 const char *res;
2486 unsigned int timeout_mail;
2487 if (!*args[2]) {
2488 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2489 file, linenum, args[0], args[1]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2494 if (res) {
2495 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2496 file, linenum, *res, args[0]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500 if (timeout_mail <= 0) {
2501 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505 curmailers->timeout.mail = timeout_mail;
2506 } else {
2507 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2508 file, linenum, args[0], args[1]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512 }
Simon Horman0d16a402015-01-30 11:22:58 +09002513 else if (*args[0] != 0) {
2514 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518
2519out:
2520 free(errmsg);
2521 return err_code;
2522}
2523
Simon Horman9dc49962015-01-30 11:22:59 +09002524static void free_email_alert(struct proxy *p)
2525{
2526 free(p->email_alert.mailers.name);
2527 p->email_alert.mailers.name = NULL;
2528 free(p->email_alert.from);
2529 p->email_alert.from = NULL;
2530 free(p->email_alert.to);
2531 p->email_alert.to = NULL;
2532 free(p->email_alert.myhostname);
2533 p->email_alert.myhostname = NULL;
2534}
2535
Willy Tarreau3842f002009-06-14 11:39:52 +02002536int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537{
2538 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002539 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002540 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002541 int rc;
2542 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002543 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002544 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002545 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002546 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002547 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548
Willy Tarreau977b8e42006-12-29 14:19:17 +01002549 if (!strcmp(args[0], "listen"))
2550 rc = PR_CAP_LISTEN;
2551 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002552 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002553 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002554 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555 else
2556 rc = PR_CAP_NONE;
2557
2558 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 if (!*args[1]) {
2560 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002561 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002566
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002567 err = invalid_char(args[1]);
2568 if (err) {
2569 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2570 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002572 }
2573
Willy Tarreau8f50b682015-05-26 11:45:02 +02002574 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2575 if (curproxy) {
2576 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2577 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2578 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002580 }
2581
Vincent Bernat02779b62016-04-03 13:48:43 +02002582 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_ABORT;
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002587
Willy Tarreau97cb7802010-01-03 20:23:58 +01002588 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 curproxy->next = proxy;
2590 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002591 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2592 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002593 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002595 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002596 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597
William Lallemand6e62fb62015-04-28 16:55:23 +02002598 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2599 if (curproxy->cap & PR_CAP_FE)
2600 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
2603
2604 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002605 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002606 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002607
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002610 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002611 curproxy->no_options = defproxy.no_options;
2612 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002613 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002614 curproxy->except_net = defproxy.except_net;
2615 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002616 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002617 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002619 if (defproxy.fwdfor_hdr_len) {
2620 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2621 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2622 }
2623
Willy Tarreaub86db342009-11-30 11:50:16 +01002624 if (defproxy.orgto_hdr_len) {
2625 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2626 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2627 }
2628
Mark Lamourinec2247f02012-01-04 13:02:01 -05002629 if (defproxy.server_id_hdr_len) {
2630 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2631 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2632 }
2633
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634 if (curproxy->cap & PR_CAP_FE) {
2635 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002636 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002637 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638
2639 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002640 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2641 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642
2643 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002647 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002648 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 curproxy->fullconn = defproxy.fullconn;
2650 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002651 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002652 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002654 if (defproxy.check_req) {
2655 curproxy->check_req = calloc(1, defproxy.check_len);
2656 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2657 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002660 if (defproxy.expect_str) {
2661 curproxy->expect_str = strdup(defproxy.expect_str);
2662 if (defproxy.expect_regex) {
2663 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002664 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2665 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002666 }
2667 }
2668
Willy Tarreau67402132012-05-31 20:40:20 +02002669 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670 if (defproxy.cookie_name)
2671 curproxy->cookie_name = strdup(defproxy.cookie_name);
2672 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002673
2674 if (defproxy.dyncookie_key)
2675 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002676 if (defproxy.cookie_domain)
2677 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002678
Willy Tarreau31936852010-10-06 16:59:56 +02002679 if (defproxy.cookie_maxidle)
2680 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2681
2682 if (defproxy.cookie_maxlife)
2683 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2684
Emeric Brun647caf12009-06-30 17:57:00 +02002685 if (defproxy.rdp_cookie_name)
2686 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2687 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2688
Willy Tarreau01732802007-11-01 22:48:15 +01002689 if (defproxy.url_param_name)
2690 curproxy->url_param_name = strdup(defproxy.url_param_name);
2691 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002692
Benoitaffb4812009-03-25 13:02:10 +01002693 if (defproxy.hh_name)
2694 curproxy->hh_name = strdup(defproxy.hh_name);
2695 curproxy->hh_len = defproxy.hh_len;
2696 curproxy->hh_match_domain = defproxy.hh_match_domain;
2697
Willy Tarreauef9a3602012-12-08 22:29:20 +01002698 if (defproxy.conn_src.iface_name)
2699 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2700 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002701 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002702#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002703 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002704#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002705 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002708 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002709 if (defproxy.capture_name)
2710 curproxy->capture_name = strdup(defproxy.capture_name);
2711 curproxy->capture_namelen = defproxy.capture_namelen;
2712 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002716 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002717 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002718 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002719 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002720 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 curproxy->mon_net = defproxy.mon_net;
2722 curproxy->mon_mask = defproxy.mon_mask;
2723 if (defproxy.monitor_uri)
2724 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2725 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002726 if (defproxy.defbe.name)
2727 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002728
2729 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002730 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2731 if (curproxy->conf.logformat_string &&
2732 curproxy->conf.logformat_string != default_http_log_format &&
2733 curproxy->conf.logformat_string != default_tcp_log_format &&
2734 curproxy->conf.logformat_string != clf_http_log_format)
2735 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2736
2737 if (defproxy.conf.lfs_file) {
2738 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2739 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2740 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002741
2742 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2743 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2744 if (curproxy->conf.logformat_sd_string &&
2745 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2746 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2747
2748 if (defproxy.conf.lfsd_file) {
2749 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2750 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752 }
2753
2754 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002755 curproxy->timeout.connect = defproxy.timeout.connect;
2756 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002757 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002758 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002759 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002760 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002761 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002762 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002763 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002764 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002765 }
2766
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002768 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002769
2770 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002771 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002772 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002773 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002774 LIST_INIT(&node->list);
2775 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2776 }
2777
Willy Tarreau62a61232013-04-12 18:13:46 +02002778 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2779 if (curproxy->conf.uniqueid_format_string)
2780 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2781
Dragan Dosen43885c72015-10-01 13:18:13 +02002782 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002783
Willy Tarreau62a61232013-04-12 18:13:46 +02002784 if (defproxy.conf.uif_file) {
2785 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2786 curproxy->conf.uif_line = defproxy.conf.uif_line;
2787 }
William Lallemanda73203e2012-03-12 12:48:57 +01002788
2789 /* copy default header unique id */
2790 if (defproxy.header_unique_id)
2791 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2792
William Lallemand82fe75c2012-10-23 10:25:10 +02002793 /* default compression options */
2794 if (defproxy.comp != NULL) {
2795 curproxy->comp = calloc(1, sizeof(struct comp));
2796 curproxy->comp->algos = defproxy.comp->algos;
2797 curproxy->comp->types = defproxy.comp->types;
2798 }
2799
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002801 curproxy->conf.used_listener_id = EB_ROOT;
2802 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002803
Simon Horman98637e52014-06-20 12:30:16 +09002804 if (defproxy.check_path)
2805 curproxy->check_path = strdup(defproxy.check_path);
2806 if (defproxy.check_command)
2807 curproxy->check_command = strdup(defproxy.check_command);
2808
Simon Horman9dc49962015-01-30 11:22:59 +09002809 if (defproxy.email_alert.mailers.name)
2810 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2811 if (defproxy.email_alert.from)
2812 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2813 if (defproxy.email_alert.to)
2814 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2815 if (defproxy.email_alert.myhostname)
2816 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002817 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002818 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002819
Willy Tarreau93893792009-07-23 13:19:11 +02002820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 }
2822 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2823 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002824 /* FIXME-20070101: we should do this too at the end of the
2825 * config parsing to free all default values.
2826 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002827 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2828 err_code |= ERR_ABORT;
2829 goto out;
2830 }
2831
Willy Tarreaua534fea2008-08-03 12:19:50 +02002832 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002833 free(defproxy.check_command);
2834 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002835 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002836 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002837 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002838 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002839 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002840 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(defproxy.capture_name);
2842 free(defproxy.monitor_uri);
2843 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002844 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002845 free(defproxy.fwdfor_hdr_name);
2846 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002847 free(defproxy.orgto_hdr_name);
2848 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002849 free(defproxy.server_id_hdr_name);
2850 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002851 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002852 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002853 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002854 free(defproxy.expect_regex);
2855 defproxy.expect_regex = NULL;
2856 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002857
Willy Tarreau62a61232013-04-12 18:13:46 +02002858 if (defproxy.conf.logformat_string != default_http_log_format &&
2859 defproxy.conf.logformat_string != default_tcp_log_format &&
2860 defproxy.conf.logformat_string != clf_http_log_format)
2861 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002862
Willy Tarreau62a61232013-04-12 18:13:46 +02002863 free(defproxy.conf.uniqueid_format_string);
2864 free(defproxy.conf.lfs_file);
2865 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002866 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002867 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002868
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002869 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2870 free(defproxy.conf.logformat_sd_string);
2871 free(defproxy.conf.lfsd_file);
2872
Willy Tarreaua534fea2008-08-03 12:19:50 +02002873 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002874 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002875
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 /* we cannot free uri_auth because it might already be used */
2877 init_default_instance();
2878 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002879 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2880 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002881 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 }
2884 else if (curproxy == NULL) {
2885 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002889
2890 /* update the current file and line being parsed */
2891 curproxy->conf.args.file = curproxy->conf.file;
2892 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002893
2894 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002895 if (!strcmp(args[0], "server") ||
2896 !strcmp(args[0], "default-server") ||
2897 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002898 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2899 if (err_code & ERR_FATAL)
2900 goto out;
2901 }
2902 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002903 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002904 int cur_arg;
2905
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 if (curproxy == &defproxy) {
2907 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002911 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913
Willy Tarreau24709282013-03-10 21:32:12 +01002914 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002915 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002920
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002921 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002922
2923 /* use default settings for unix sockets */
2924 bind_conf->ux.uid = global.unix_bind.ux.uid;
2925 bind_conf->ux.gid = global.unix_bind.ux.gid;
2926 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002927
2928 /* NOTE: the following line might create several listeners if there
2929 * are comma-separated IPs or port ranges. So all further processing
2930 * will have to be applied to all listeners created after last_listen.
2931 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002932 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2933 if (errmsg && *errmsg) {
2934 indent_msg(&errmsg, 2);
2935 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002936 }
2937 else
2938 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2939 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002943
Willy Tarreau4348fad2012-09-20 16:48:07 +02002944 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2945 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002946 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002947 }
2948
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002949 cur_arg = 2;
2950 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002951 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002952 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002953 char *err;
2954
Willy Tarreau26982662012-09-12 23:17:10 +02002955 kw = bind_find_kw(args[cur_arg]);
2956 if (kw) {
2957 char *err = NULL;
2958 int code;
2959
2960 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002961 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2962 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002963 cur_arg += 1 + kw->skip ;
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967
Willy Tarreau4348fad2012-09-20 16:48:07 +02002968 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002969 err_code |= code;
2970
2971 if (code) {
2972 if (err && *err) {
2973 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002974 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002975 }
2976 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002977 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2978 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002979 if (code & ERR_FATAL) {
2980 free(err);
2981 cur_arg += 1 + kw->skip;
2982 goto out;
2983 }
2984 }
2985 free(err);
2986 cur_arg += 1 + kw->skip;
2987 continue;
2988 }
2989
Willy Tarreau8638f482012-09-18 18:01:17 +02002990 err = NULL;
2991 if (!bind_dumped) {
2992 bind_dump_kws(&err);
2993 indent_msg(&err, 4);
2994 bind_dumped = 1;
2995 }
2996
2997 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2998 file, linenum, args[0], args[1], args[cur_arg],
2999 err ? " Registered keywords :" : "", err ? err : "");
3000 free(err);
3001
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003004 }
Willy Tarreau93893792009-07-23 13:19:11 +02003005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 }
3007 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003008 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003014 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003016
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 /* flush useless bits */
3018 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003021 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003024
William Lallemanddf1425a2015-04-28 20:17:49 +02003025 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3026 goto out;
3027
Willy Tarreau1c47f852006-07-09 08:22:27 +02003028 if (!*args[1]) {
3029 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003033 }
3034
Willy Tarreaua534fea2008-08-03 12:19:50 +02003035 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003036 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003037 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003038 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003039 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3040
Willy Tarreau93893792009-07-23 13:19:11 +02003041 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003044 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3045 goto out;
3046
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3048 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3049 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3050 else {
3051 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
3055 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003056 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003057 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003058
3059 if (curproxy == &defproxy) {
3060 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064 }
3065
William Lallemanddf1425a2015-04-28 20:17:49 +02003066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3067 goto out;
3068
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003069 if (!*args[1]) {
3070 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003074 }
3075
3076 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003077 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003078 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003079
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003080 if (curproxy->uuid <= 0) {
3081 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003082 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003085 }
3086
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003087 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3088 if (node) {
3089 struct proxy *target = container_of(node, struct proxy, conf.id);
3090 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3091 file, linenum, proxy_type_str(curproxy), curproxy->id,
3092 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003097 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003098 else if (!strcmp(args[0], "description")) {
3099 int i, len=0;
3100 char *d;
3101
Cyril Bonté99ed3272010-01-24 23:29:44 +01003102 if (curproxy == &defproxy) {
3103 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3104 file, linenum, args[0]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003109 if (!*args[1]) {
3110 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3111 file, linenum, args[0]);
3112 return -1;
3113 }
3114
Willy Tarreau348acfe2014-04-14 15:00:39 +02003115 for (i = 1; *args[i]; i++)
3116 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003117
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003118 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003119 curproxy->desc = d;
3120
Willy Tarreau348acfe2014-04-14 15:00:39 +02003121 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3122 for (i = 2; *args[i]; i++)
3123 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003124
3125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003127 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 curproxy->state = PR_STSTOPPED;
3130 }
3131 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003132 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 curproxy->state = PR_STNEW;
3135 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003136 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3137 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003138 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003139
3140 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003141 unsigned int low, high;
3142
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003143 if (strcmp(args[cur_arg], "all") == 0) {
3144 set = 0;
3145 break;
3146 }
3147 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003148 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003149 }
3150 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003151 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003152 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003153 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003154 char *dash = strchr(args[cur_arg], '-');
3155
3156 low = high = str2uic(args[cur_arg]);
3157 if (dash)
3158 high = str2uic(dash + 1);
3159
3160 if (high < low) {
3161 unsigned int swap = low;
3162 low = high;
3163 high = swap;
3164 }
3165
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003166 if (low < 1 || high > LONGBITS) {
3167 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3168 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003171 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003172 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003173 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003174 }
3175 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003176 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3177 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003180 }
3181 cur_arg++;
3182 }
3183 curproxy->bind_proc = set;
3184 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003185 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003186 if (curproxy == &defproxy) {
3187 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003190 }
3191
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003192 err = invalid_char(args[1]);
3193 if (err) {
3194 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3195 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003197 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003198 }
3199
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003200 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003201 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3202 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003205 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003206 }
3207 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3208
3209 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3210 err_code |= ERR_WARN;
3211
3212 if (*(args[1]) == 0) {
3213 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3214 file, linenum, args[0]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218 free(curproxy->dyncookie_key);
3219 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3222 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223
Willy Tarreau977b8e42006-12-29 14:19:17 +01003224 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 if (*(args[1]) == 0) {
3228 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3229 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003233
Willy Tarreau67402132012-05-31 20:40:20 +02003234 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003235 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003236 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003237 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 curproxy->cookie_name = strdup(args[1]);
3239 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 cur_arg = 2;
3242 while (*(args[cur_arg])) {
3243 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003244 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
3246 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003247 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 }
3249 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003250 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 }
3252 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003253 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 }
3255 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003256 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003258 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003259 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003262 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003264 else if (!strcmp(args[cur_arg], "httponly")) {
3265 curproxy->ck_opts |= PR_CK_HTTPONLY;
3266 }
3267 else if (!strcmp(args[cur_arg], "secure")) {
3268 curproxy->ck_opts |= PR_CK_SECURE;
3269 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003270 else if (!strcmp(args[cur_arg], "domain")) {
3271 if (!*args[cur_arg + 1]) {
3272 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3273 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003276 }
3277
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003278 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003279 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003280 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3281 " dots nor does not start with a dot."
3282 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003283 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003284 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003285 }
3286
3287 err = invalid_domainchar(args[cur_arg + 1]);
3288 if (err) {
3289 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3290 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003293 }
3294
Willy Tarreau68a897b2009-12-03 23:28:34 +01003295 if (!curproxy->cookie_domain) {
3296 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3297 } else {
3298 /* one domain was already specified, add another one by
3299 * building the string which will be returned along with
3300 * the cookie.
3301 */
3302 char *new_ptr;
3303 int new_len = strlen(curproxy->cookie_domain) +
3304 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3305 new_ptr = malloc(new_len);
3306 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3307 free(curproxy->cookie_domain);
3308 curproxy->cookie_domain = new_ptr;
3309 }
Willy Tarreau31936852010-10-06 16:59:56 +02003310 cur_arg++;
3311 }
3312 else if (!strcmp(args[cur_arg], "maxidle")) {
3313 unsigned int maxidle;
3314 const char *res;
3315
3316 if (!*args[cur_arg + 1]) {
3317 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3318 file, linenum, args[cur_arg]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
3322
3323 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3324 if (res) {
3325 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3326 file, linenum, *res, args[cur_arg]);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
3330 curproxy->cookie_maxidle = maxidle;
3331 cur_arg++;
3332 }
3333 else if (!strcmp(args[cur_arg], "maxlife")) {
3334 unsigned int maxlife;
3335 const char *res;
3336
3337 if (!*args[cur_arg + 1]) {
3338 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3339 file, linenum, args[cur_arg]);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
3343
3344 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3345 if (res) {
3346 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3347 file, linenum, *res, args[cur_arg]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003352 cur_arg++;
3353 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003354 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003355
3356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3357 err_code |= ERR_WARN;
3358 curproxy->ck_opts |= PR_CK_DYNAMIC;
3359 }
3360
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003362 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 cur_arg++;
3368 }
Willy Tarreau67402132012-05-31 20:40:20 +02003369 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3371 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374
Willy Tarreau67402132012-05-31 20:40:20 +02003375 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003380
Willy Tarreau67402132012-05-31 20:40:20 +02003381 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003382 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3383 file, linenum);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003387 else if (!strcmp(args[0], "email-alert")) {
3388 if (*(args[1]) == 0) {
3389 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3390 file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (!strcmp(args[1], "from")) {
3396 if (*(args[1]) == 0) {
3397 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3398 file, linenum, args[1]);
3399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
3402 free(curproxy->email_alert.from);
3403 curproxy->email_alert.from = strdup(args[2]);
3404 }
3405 else if (!strcmp(args[1], "mailers")) {
3406 if (*(args[1]) == 0) {
3407 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3408 file, linenum, args[1]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412 free(curproxy->email_alert.mailers.name);
3413 curproxy->email_alert.mailers.name = strdup(args[2]);
3414 }
3415 else if (!strcmp(args[1], "myhostname")) {
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 free(curproxy->email_alert.myhostname);
3423 curproxy->email_alert.myhostname = strdup(args[2]);
3424 }
Simon Horman64e34162015-02-06 11:11:57 +09003425 else if (!strcmp(args[1], "level")) {
3426 curproxy->email_alert.level = get_log_level(args[2]);
3427 if (curproxy->email_alert.level < 0) {
3428 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3429 file, linenum, args[1], args[2]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433 }
Simon Horman9dc49962015-01-30 11:22:59 +09003434 else if (!strcmp(args[1], "to")) {
3435 if (*(args[1]) == 0) {
3436 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3437 file, linenum, args[1]);
3438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
3440 }
3441 free(curproxy->email_alert.to);
3442 curproxy->email_alert.to = strdup(args[2]);
3443 }
3444 else {
3445 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3446 file, linenum, args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
Simon Horman64e34162015-02-06 11:11:57 +09003450 /* Indicate that the email_alert is at least partially configured */
3451 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003452 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003453 else if (!strcmp(args[0], "external-check")) {
3454 if (*(args[1]) == 0) {
3455 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3456 file, linenum, args[0]);
3457 err_code |= ERR_ALERT | ERR_FATAL;
3458 goto out;
3459 }
3460
3461 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003462 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003463 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003464 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003465 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3466 file, linenum, args[1]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
3470 free(curproxy->check_command);
3471 curproxy->check_command = strdup(args[2]);
3472 }
3473 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003474 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003475 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003476 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003477 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3478 file, linenum, args[1]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482 free(curproxy->check_path);
3483 curproxy->check_path = strdup(args[2]);
3484 }
3485 else {
3486 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3487 file, linenum, args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003492 else if (!strcmp(args[0], "persist")) { /* persist */
3493 if (*(args[1]) == 0) {
3494 Alert("parsing [%s:%d] : missing persist method.\n",
3495 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003498 }
3499
3500 if (!strncmp(args[1], "rdp-cookie", 10)) {
3501 curproxy->options2 |= PR_O2_RDPC_PRST;
3502
Emeric Brunb982a3d2010-01-04 15:45:53 +01003503 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003504 const char *beg, *end;
3505
3506 beg = args[1] + 11;
3507 end = strchr(beg, ')');
3508
William Lallemanddf1425a2015-04-28 20:17:49 +02003509 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3510 goto out;
3511
Emeric Brun647caf12009-06-30 17:57:00 +02003512 if (!end || end == beg) {
3513 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3514 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003517 }
3518
3519 free(curproxy->rdp_cookie_name);
3520 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3521 curproxy->rdp_cookie_len = end-beg;
3522 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003523 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003524 free(curproxy->rdp_cookie_name);
3525 curproxy->rdp_cookie_name = strdup("msts");
3526 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3527 }
3528 else { /* syntax */
3529 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3530 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003533 }
3534 }
3535 else {
3536 Alert("parsing [%s:%d] : unknown persist method.\n",
3537 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003540 }
3541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003543 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003547 else if (!strcmp(args[0], "load-server-state-from-file")) {
3548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3549 err_code |= ERR_WARN;
3550 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3551 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3552 }
3553 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3554 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3555 }
3556 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3557 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3558 }
3559 else {
3560 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3561 file, linenum, args[0], args[1]);
3562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
3564 }
3565 }
3566 else if (!strcmp(args[0], "server-state-file-name")) {
3567 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3568 err_code |= ERR_WARN;
3569 if (*(args[1]) == 0) {
3570 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3571 file, linenum, args[0]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 else if (!strcmp(args[1], "use-backend-name"))
3576 curproxy->server_state_file_name = strdup(curproxy->id);
3577 else
3578 curproxy->server_state_file_name = strdup(args[1]);
3579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003581 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003583
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003585 if (curproxy == &defproxy) {
3586 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590
William Lallemand1a748ae2015-05-19 16:37:23 +02003591 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3592 goto out;
3593
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 if (*(args[4]) == 0) {
3595 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003600 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 curproxy->capture_name = strdup(args[2]);
3602 curproxy->capture_namelen = strlen(curproxy->capture_name);
3603 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 curproxy->to_log |= LW_COOKIE;
3605 }
3606 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3607 struct cap_hdr *hdr;
3608
3609 if (curproxy == &defproxy) {
3610 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 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
3614
William Lallemand1a748ae2015-05-19 16:37:23 +02003615 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3616 goto out;
3617
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3619 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3620 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 }
3624
Vincent Bernat02779b62016-04-03 13:48:43 +02003625 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 hdr->next = curproxy->req_cap;
3627 hdr->name = strdup(args[3]);
3628 hdr->namelen = strlen(args[3]);
3629 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003630 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 hdr->index = curproxy->nb_req_cap++;
3632 curproxy->req_cap = hdr;
3633 curproxy->to_log |= LW_REQHDR;
3634 }
3635 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3636 struct cap_hdr *hdr;
3637
3638 if (curproxy == &defproxy) {
3639 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 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643
William Lallemand1a748ae2015-05-19 16:37:23 +02003644 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3645 goto out;
3646
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3648 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3649 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003653 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 hdr->next = curproxy->rsp_cap;
3655 hdr->name = strdup(args[3]);
3656 hdr->namelen = strlen(args[3]);
3657 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003658 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 hdr->index = curproxy->nb_rsp_cap++;
3660 curproxy->rsp_cap = hdr;
3661 curproxy->to_log |= LW_RSPHDR;
3662 }
3663 else {
3664 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
3669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003673
William Lallemanddf1425a2015-04-28 20:17:49 +02003674 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3675 goto out;
3676
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 if (*(args[1]) == 0) {
3678 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3679 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
3683 curproxy->conn_retries = atol(args[1]);
3684 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003685 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003686 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003687
3688 if (curproxy == &defproxy) {
3689 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693
Willy Tarreau20b0de52012-12-24 15:45:22 +01003694 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003695 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003696 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3697 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3698 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3699 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003700 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 +01003701 file, linenum, args[0]);
3702 err_code |= ERR_WARN;
3703 }
3704
Willy Tarreauff011f22011-01-06 17:51:27 +01003705 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003706
Willy Tarreauff011f22011-01-06 17:51:27 +01003707 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003708 err_code |= ERR_ALERT | ERR_ABORT;
3709 goto out;
3710 }
3711
Willy Tarreau5002f572014-04-23 01:32:02 +02003712 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003713 err_code |= warnif_cond_conflicts(rule->cond,
3714 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3715 file, linenum);
3716
Willy Tarreauff011f22011-01-06 17:51:27 +01003717 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003718 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003719 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003720 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003721
3722 if (curproxy == &defproxy) {
3723 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727
3728 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003729 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003730 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3731 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003732 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3733 file, linenum, args[0]);
3734 err_code |= ERR_WARN;
3735 }
3736
3737 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3738
3739 if (!rule) {
3740 err_code |= ERR_ALERT | ERR_ABORT;
3741 goto out;
3742 }
3743
3744 err_code |= warnif_cond_conflicts(rule->cond,
3745 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3746 file, linenum);
3747
3748 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3749 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003750 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3751 /* set the header name and length into the proxy structure */
3752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3753 err_code |= ERR_WARN;
3754
3755 if (!*args[1]) {
3756 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3757 file, linenum, args[0]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761
3762 /* set the desired header name */
3763 free(curproxy->server_id_hdr_name);
3764 curproxy->server_id_hdr_name = strdup(args[1]);
3765 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3766 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003767 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003768 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003769
Willy Tarreaub099aca2008-10-12 17:26:37 +02003770 if (curproxy == &defproxy) {
3771 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003774 }
3775
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003776 /* emulate "block" using "http-request block". Since these rules are supposed to
3777 * be processed before all http-request rules, we put them into their own list
3778 * and will insert them at the end.
3779 */
3780 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3781 if (!rule) {
3782 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003783 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003784 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003785 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3786 err_code |= warnif_cond_conflicts(rule->cond,
3787 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3788 file, linenum);
3789 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003790
3791 if (!already_warned(WARN_BLOCK_DEPRECATED))
3792 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]);
3793
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003794 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003795 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003796 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003797
Cyril Bonté99ed3272010-01-24 23:29:44 +01003798 if (curproxy == &defproxy) {
3799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803
Willy Tarreaube4653b2015-05-28 15:26:58 +02003804 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003805 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3806 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003809 }
3810
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003811 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003812 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003813 err_code |= warnif_cond_conflicts(rule->cond,
3814 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3815 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003816 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003817 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003818 struct switching_rule *rule;
3819
Willy Tarreaub099aca2008-10-12 17:26:37 +02003820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003824 }
3825
Willy Tarreau55ea7572007-06-17 19:56:27 +02003826 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003828
3829 if (*(args[1]) == 0) {
3830 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003833 }
3834
Willy Tarreauf51658d2014-04-23 01:21:56 +02003835 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3836 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3837 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3838 file, linenum, errmsg);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003842
Willy Tarreauf51658d2014-04-23 01:21:56 +02003843 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003844 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003845 else if (*args[2]) {
3846 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3847 file, linenum, args[2]);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003852 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003853 if (!rule) {
3854 Alert("Out of memory error.\n");
3855 goto out;
3856 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003857 rule->cond = cond;
3858 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003859 rule->line = linenum;
3860 rule->file = strdup(file);
3861 if (!rule->file) {
3862 Alert("Out of memory error.\n");
3863 goto out;
3864 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003865 LIST_INIT(&rule->list);
3866 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3867 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003868 else if (strcmp(args[0], "use-server") == 0) {
3869 struct server_rule *rule;
3870
3871 if (curproxy == &defproxy) {
3872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876
3877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3878 err_code |= ERR_WARN;
3879
3880 if (*(args[1]) == 0) {
3881 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
3886 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3887 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3888 file, linenum, args[0]);
3889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
3891 }
3892
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003893 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3894 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3895 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
3898 }
3899
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003900 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003901
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003902 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003903 rule->cond = cond;
3904 rule->srv.name = strdup(args[1]);
3905 LIST_INIT(&rule->list);
3906 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3907 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3908 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003909 else if ((!strcmp(args[0], "force-persist")) ||
3910 (!strcmp(args[0], "ignore-persist"))) {
3911 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003912
3913 if (curproxy == &defproxy) {
3914 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
3917 }
3918
3919 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3920 err_code |= ERR_WARN;
3921
Willy Tarreauef6494c2010-01-28 17:12:36 +01003922 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003923 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3924 file, linenum, args[0]);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003929 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3930 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3931 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
3934 }
3935
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003936 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3937 * where force-persist is applied.
3938 */
3939 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003940
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003941 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003942 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003943 if (!strcmp(args[0], "force-persist")) {
3944 rule->type = PERSIST_TYPE_FORCE;
3945 } else {
3946 rule->type = PERSIST_TYPE_IGNORE;
3947 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003948 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003949 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003950 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003951 else if (!strcmp(args[0], "stick-table")) {
3952 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003953 struct proxy *other;
3954
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003955 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003956 if (other) {
3957 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3958 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003962
Emeric Brun32da3c42010-09-23 18:39:19 +02003963 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003964 curproxy->table.type = (unsigned int)-1;
3965 while (*args[myidx]) {
3966 const char *err;
3967
3968 if (strcmp(args[myidx], "size") == 0) {
3969 myidx++;
3970 if (!*(args[myidx])) {
3971 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3972 file, linenum, args[myidx-1]);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
3976 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3977 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3978 file, linenum, *err, args[myidx-1]);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003982 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003983 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003984 else if (strcmp(args[myidx], "peers") == 0) {
3985 myidx++;
Godbach50523162013-12-11 19:48:57 +08003986 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003987 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3988 file, linenum, args[myidx-1]);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Godbach50523162013-12-11 19:48:57 +08003991 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003992 curproxy->table.peers.name = strdup(args[myidx++]);
3993 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003994 else if (strcmp(args[myidx], "expire") == 0) {
3995 myidx++;
3996 if (!*(args[myidx])) {
3997 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3998 file, linenum, args[myidx-1]);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4003 if (err) {
4004 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4005 file, linenum, *err, args[myidx-1]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004009 if (val > INT_MAX) {
4010 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4011 file, linenum, val);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004015 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004016 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 }
4018 else if (strcmp(args[myidx], "nopurge") == 0) {
4019 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004020 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004021 }
4022 else if (strcmp(args[myidx], "type") == 0) {
4023 myidx++;
4024 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4025 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4026 file, linenum, args[myidx]);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004030 /* myidx already points to next arg */
4031 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004032 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004033 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004034 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004035
4036 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004037 nw = args[myidx];
4038 while (*nw) {
4039 /* the "store" keyword supports a comma-separated list */
4040 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004041 sa = NULL; /* store arg */
4042 while (*nw && *nw != ',') {
4043 if (*nw == '(') {
4044 *nw = 0;
4045 sa = ++nw;
4046 while (*nw != ')') {
4047 if (!*nw) {
4048 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4049 file, linenum, args[0], cw);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053 nw++;
4054 }
4055 *nw = '\0';
4056 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004057 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004058 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004059 if (*nw)
4060 *nw++ = '\0';
4061 type = stktable_get_data_type(cw);
4062 if (type < 0) {
4063 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4064 file, linenum, args[0], cw);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
Willy Tarreauac782882010-06-20 10:41:54 +02004068
4069 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4070 switch (err) {
4071 case PE_NONE: break;
4072 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004073 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4074 file, linenum, args[0], cw);
4075 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004076 break;
4077
4078 case PE_ARG_MISSING:
4079 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4080 file, linenum, args[0], cw);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083
4084 case PE_ARG_NOT_USED:
4085 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4086 file, linenum, args[0], cw);
4087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
4089
4090 default:
4091 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4092 file, linenum, args[0], cw);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004095 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004096 }
4097 myidx++;
4098 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004099 else {
4100 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4101 file, linenum, args[myidx]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004104 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004105 }
4106
4107 if (!curproxy->table.size) {
4108 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4109 file, linenum);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113
4114 if (curproxy->table.type == (unsigned int)-1) {
4115 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4116 file, linenum);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 }
4121 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004122 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004123 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 int myidx = 0;
4125 const char *name = NULL;
4126 int flags;
4127
4128 if (curproxy == &defproxy) {
4129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133
4134 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4135 err_code |= ERR_WARN;
4136 goto out;
4137 }
4138
4139 myidx++;
4140 if ((strcmp(args[myidx], "store") == 0) ||
4141 (strcmp(args[myidx], "store-request") == 0)) {
4142 myidx++;
4143 flags = STK_IS_STORE;
4144 }
4145 else if (strcmp(args[myidx], "store-response") == 0) {
4146 myidx++;
4147 flags = STK_IS_STORE | STK_ON_RSP;
4148 }
4149 else if (strcmp(args[myidx], "match") == 0) {
4150 myidx++;
4151 flags = STK_IS_MATCH;
4152 }
4153 else if (strcmp(args[myidx], "on") == 0) {
4154 myidx++;
4155 flags = STK_IS_MATCH | STK_IS_STORE;
4156 }
4157 else {
4158 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162
4163 if (*(args[myidx]) == 0) {
4164 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
4167 }
4168
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004169 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004170 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004171 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004172 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175 }
4176
4177 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004178 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4179 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4180 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004181 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004182 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004183 goto out;
4184 }
4185 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004186 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4187 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4188 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004189 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004190 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004191 goto out;
4192 }
4193 }
4194
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004195 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004196 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004197
Emeric Brunb982a3d2010-01-04 15:45:53 +01004198 if (strcmp(args[myidx], "table") == 0) {
4199 myidx++;
4200 name = args[myidx++];
4201 }
4202
Willy Tarreauef6494c2010-01-28 17:12:36 +01004203 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004204 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4205 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4206 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004208 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004209 goto out;
4210 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004211 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004212 else if (*(args[myidx])) {
4213 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4214 file, linenum, args[0], args[myidx]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004216 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004217 goto out;
4218 }
Emeric Brun97679e72010-09-23 17:56:44 +02004219 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004220 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004221 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004222 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004223
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004224 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 rule->cond = cond;
4226 rule->expr = expr;
4227 rule->flags = flags;
4228 rule->table.name = name ? strdup(name) : NULL;
4229 LIST_INIT(&rule->list);
4230 if (flags & STK_ON_RSP)
4231 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4232 else
4233 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 else if (!strcmp(args[0], "stats")) {
4236 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4237 curproxy->uri_auth = NULL; /* we must detach from the default config */
4238
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004239 if (!*args[1]) {
4240 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004241 } else if (!strcmp(args[1], "admin")) {
4242 struct stats_admin_rule *rule;
4243
4244 if (curproxy == &defproxy) {
4245 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
4250 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4251 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4252 err_code |= ERR_ALERT | ERR_ABORT;
4253 goto out;
4254 }
4255
4256 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4257 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4258 file, linenum, args[0], args[1]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004262 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4263 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4264 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004269 err_code |= warnif_cond_conflicts(cond,
4270 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4271 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004272
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004273 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004274 rule->cond = cond;
4275 LIST_INIT(&rule->list);
4276 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 } else if (!strcmp(args[1], "uri")) {
4278 if (*(args[2]) == 0) {
4279 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_ABORT;
4285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 }
4287 } else if (!strcmp(args[1], "realm")) {
4288 if (*(args[2]) == 0) {
4289 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_ABORT;
4295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004297 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004298 unsigned interval;
4299
4300 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4301 if (err) {
4302 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4303 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004306 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004310 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004311 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004312 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004313
4314 if (curproxy == &defproxy) {
4315 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319
4320 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4321 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4322 err_code |= ERR_ALERT | ERR_ABORT;
4323 goto out;
4324 }
4325
Willy Tarreauff011f22011-01-06 17:51:27 +01004326 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004327 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004328 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4329 file, linenum, args[0]);
4330 err_code |= ERR_WARN;
4331 }
4332
Willy Tarreauff011f22011-01-06 17:51:27 +01004333 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004334
Willy Tarreauff011f22011-01-06 17:51:27 +01004335 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004336 err_code |= ERR_ALERT | ERR_ABORT;
4337 goto out;
4338 }
4339
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004340 err_code |= warnif_cond_conflicts(rule->cond,
4341 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4342 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004343 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004344
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 } else if (!strcmp(args[1], "auth")) {
4346 if (*(args[2]) == 0) {
4347 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4351 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004352 err_code |= ERR_ALERT | ERR_ABORT;
4353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354 }
4355 } else if (!strcmp(args[1], "scope")) {
4356 if (*(args[2]) == 0) {
4357 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004362 err_code |= ERR_ALERT | ERR_ABORT;
4363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004364 }
4365 } else if (!strcmp(args[1], "enable")) {
4366 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_ABORT;
4369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004371 } else if (!strcmp(args[1], "hide-version")) {
4372 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_ABORT;
4375 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004376 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004377 } else if (!strcmp(args[1], "show-legends")) {
4378 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4380 err_code |= ERR_ALERT | ERR_ABORT;
4381 goto out;
4382 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004383 } else if (!strcmp(args[1], "show-node")) {
4384
4385 if (*args[2]) {
4386 int i;
4387 char c;
4388
4389 for (i=0; args[2][i]; i++) {
4390 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004391 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4392 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004393 break;
4394 }
4395
4396 if (!i || args[2][i]) {
4397 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4398 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4399 file, linenum, args[0], args[1]);
4400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
4403 }
4404
4405 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4406 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4407 err_code |= ERR_ALERT | ERR_ABORT;
4408 goto out;
4409 }
4410 } else if (!strcmp(args[1], "show-desc")) {
4411 char *desc = NULL;
4412
4413 if (*args[2]) {
4414 int i, len=0;
4415 char *d;
4416
Willy Tarreau348acfe2014-04-14 15:00:39 +02004417 for (i = 2; *args[i]; i++)
4418 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004419
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004420 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004421
Willy Tarreau348acfe2014-04-14 15:00:39 +02004422 d += snprintf(d, desc + len - d, "%s", args[2]);
4423 for (i = 3; *args[i]; i++)
4424 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004425 }
4426
4427 if (!*args[2] && !global.desc)
4428 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4429 file, linenum, args[1]);
4430 else {
4431 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4432 free(desc);
4433 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4434 err_code |= ERR_ALERT | ERR_ABORT;
4435 goto out;
4436 }
4437 free(desc);
4438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004440stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004441 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 +01004442 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
4446 }
4447 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004448 int optnum;
4449
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004450 if (*(args[1]) == '\0') {
4451 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4452 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004456
4457 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4458 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004459 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4460 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4461 file, linenum, cfg_opts[optnum].name);
4462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
4464 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004465 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4466 goto out;
4467
Willy Tarreau93893792009-07-23 13:19:11 +02004468 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4469 err_code |= ERR_WARN;
4470 goto out;
4471 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004472
Willy Tarreau3842f002009-06-14 11:39:52 +02004473 curproxy->no_options &= ~cfg_opts[optnum].val;
4474 curproxy->options &= ~cfg_opts[optnum].val;
4475
4476 switch (kwm) {
4477 case KWM_STD:
4478 curproxy->options |= cfg_opts[optnum].val;
4479 break;
4480 case KWM_NO:
4481 curproxy->no_options |= cfg_opts[optnum].val;
4482 break;
4483 case KWM_DEF: /* already cleared */
4484 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004485 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004486
Willy Tarreau93893792009-07-23 13:19:11 +02004487 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004488 }
4489 }
4490
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004491 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4492 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004493 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4494 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4495 file, linenum, cfg_opts2[optnum].name);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4500 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004501 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4502 err_code |= ERR_WARN;
4503 goto out;
4504 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004505
Willy Tarreau3842f002009-06-14 11:39:52 +02004506 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4507 curproxy->options2 &= ~cfg_opts2[optnum].val;
4508
4509 switch (kwm) {
4510 case KWM_STD:
4511 curproxy->options2 |= cfg_opts2[optnum].val;
4512 break;
4513 case KWM_NO:
4514 curproxy->no_options2 |= cfg_opts2[optnum].val;
4515 break;
4516 case KWM_DEF: /* already cleared */
4517 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004518 }
Willy Tarreau93893792009-07-23 13:19:11 +02004519 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004520 }
4521 }
4522
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004523 /* HTTP options override each other. They can be cancelled using
4524 * "no option xxx" which only switches to default mode if the mode
4525 * was this one (useful for cancelling options set in defaults
4526 * sections).
4527 */
4528 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004529 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4530 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004531 if (kwm == KWM_STD) {
4532 curproxy->options &= ~PR_O_HTTP_MODE;
4533 curproxy->options |= PR_O_HTTP_PCL;
4534 goto out;
4535 }
4536 else if (kwm == KWM_NO) {
4537 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4538 curproxy->options &= ~PR_O_HTTP_MODE;
4539 goto out;
4540 }
4541 }
4542 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004543 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4544 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004545 if (kwm == KWM_STD) {
4546 curproxy->options &= ~PR_O_HTTP_MODE;
4547 curproxy->options |= PR_O_HTTP_FCL;
4548 goto out;
4549 }
4550 else if (kwm == KWM_NO) {
4551 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4552 curproxy->options &= ~PR_O_HTTP_MODE;
4553 goto out;
4554 }
4555 }
4556 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004557 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4558 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004559 if (kwm == KWM_STD) {
4560 curproxy->options &= ~PR_O_HTTP_MODE;
4561 curproxy->options |= PR_O_HTTP_SCL;
4562 goto out;
4563 }
4564 else if (kwm == KWM_NO) {
4565 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 goto out;
4568 }
4569 }
4570 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004571 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4572 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004573 if (kwm == KWM_STD) {
4574 curproxy->options &= ~PR_O_HTTP_MODE;
4575 curproxy->options |= PR_O_HTTP_KAL;
4576 goto out;
4577 }
4578 else if (kwm == KWM_NO) {
4579 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 goto out;
4582 }
4583 }
4584 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004585 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4586 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004587 if (kwm == KWM_STD) {
4588 curproxy->options &= ~PR_O_HTTP_MODE;
4589 curproxy->options |= PR_O_HTTP_TUN;
4590 goto out;
4591 }
4592 else if (kwm == KWM_NO) {
4593 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 goto out;
4596 }
4597 }
4598
Joseph Lynch726ab712015-05-11 23:25:34 -07004599 /* Redispatch can take an integer argument that control when the
4600 * resispatch occurs. All values are relative to the retries option.
4601 * This can be cancelled using "no option xxx".
4602 */
4603 if (strcmp(args[1], "redispatch") == 0) {
4604 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4605 err_code |= ERR_WARN;
4606 goto out;
4607 }
4608
4609 curproxy->no_options &= ~PR_O_REDISP;
4610 curproxy->options &= ~PR_O_REDISP;
4611
4612 switch (kwm) {
4613 case KWM_STD:
4614 curproxy->options |= PR_O_REDISP;
4615 curproxy->redispatch_after = -1;
4616 if(*args[2]) {
4617 curproxy->redispatch_after = atol(args[2]);
4618 }
4619 break;
4620 case KWM_NO:
4621 curproxy->no_options |= PR_O_REDISP;
4622 curproxy->redispatch_after = 0;
4623 break;
4624 case KWM_DEF: /* already cleared */
4625 break;
4626 }
4627 goto out;
4628 }
4629
Willy Tarreau3842f002009-06-14 11:39:52 +02004630 if (kwm != KWM_STD) {
4631 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004632 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004635 }
4636
Emeric Brun3a058f32009-06-30 18:26:00 +02004637 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004638 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004640 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004641 if (*(args[2]) != '\0') {
4642 if (!strcmp(args[2], "clf")) {
4643 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004644 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004645 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004646 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004649 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004650 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4651 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004652 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004653 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4654 char *oldlogformat = "log-format";
4655 char *clflogformat = "";
4656
4657 if (curproxy->conf.logformat_string == default_http_log_format)
4658 oldlogformat = "option httplog";
4659 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4660 oldlogformat = "option tcplog";
4661 else if (curproxy->conf.logformat_string == clf_http_log_format)
4662 oldlogformat = "option httplog clf";
4663 if (logformat == clf_http_log_format)
4664 clflogformat = " clf";
4665 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4666 file, linenum, clflogformat, oldlogformat);
4667 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004668 if (curproxy->conf.logformat_string != default_http_log_format &&
4669 curproxy->conf.logformat_string != default_tcp_log_format &&
4670 curproxy->conf.logformat_string != clf_http_log_format)
4671 free(curproxy->conf.logformat_string);
4672 curproxy->conf.logformat_string = logformat;
4673
4674 free(curproxy->conf.lfs_file);
4675 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4676 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004677 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004678 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004679 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4680 char *oldlogformat = "log-format";
4681
4682 if (curproxy->conf.logformat_string == default_http_log_format)
4683 oldlogformat = "option httplog";
4684 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4685 oldlogformat = "option tcplog";
4686 else if (curproxy->conf.logformat_string == clf_http_log_format)
4687 oldlogformat = "option httplog clf";
4688 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4689 file, linenum, oldlogformat);
4690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004692 if (curproxy->conf.logformat_string != default_http_log_format &&
4693 curproxy->conf.logformat_string != default_tcp_log_format &&
4694 curproxy->conf.logformat_string != clf_http_log_format)
4695 free(curproxy->conf.logformat_string);
4696 curproxy->conf.logformat_string = default_tcp_log_format;
4697
4698 free(curproxy->conf.lfs_file);
4699 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4700 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004701
4702 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4703 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004706 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004707 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004709
William Lallemanddf1425a2015-04-28 20:17:49 +02004710 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4711 goto out;
4712
Willy Tarreau13943ab2006-12-31 00:24:10 +01004713 if (curproxy->cap & PR_CAP_FE)
4714 curproxy->options |= PR_O_TCP_CLI_KA;
4715 if (curproxy->cap & PR_CAP_BE)
4716 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 }
4718 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_WARN;
4721
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004723 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004724 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004725 curproxy->options2 &= ~PR_O2_CHK_ANY;
4726 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 if (!*args[2]) { /* no argument */
4728 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4729 curproxy->check_len = strlen(DEF_CHECK_REQ);
4730 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004731 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004732 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004734 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004736 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 if (*args[4])
4738 reqlen += strlen(args[4]);
4739 else
4740 reqlen += strlen("HTTP/1.0");
4741
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004742 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004744 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004746 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4747 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004748 }
4749 else if (!strcmp(args[1], "ssl-hello-chk")) {
4750 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004753
Willy Tarreaua534fea2008-08-03 12:19:50 +02004754 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004755 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004756 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004757 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004758
4759 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
Willy Tarreau23677902007-05-08 23:50:35 +02004762 else if (!strcmp(args[1], "smtpchk")) {
4763 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004764 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004765 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004766 curproxy->options2 &= ~PR_O2_CHK_ANY;
4767 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004768
4769 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4770 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4771 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4772 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4773 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4774 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004775 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004776 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4777 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4778 } else {
4779 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4780 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4781 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4782 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4783 }
4784 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004785 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4786 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004787 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004788 else if (!strcmp(args[1], "pgsql-check")) {
4789 /* use PostgreSQL request to check servers' health */
4790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4791 err_code |= ERR_WARN;
4792
4793 free(curproxy->check_req);
4794 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004795 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004796 curproxy->options2 |= PR_O2_PGSQL_CHK;
4797
4798 if (*(args[2])) {
4799 int cur_arg = 2;
4800
4801 while (*(args[cur_arg])) {
4802 if (strcmp(args[cur_arg], "user") == 0) {
4803 char * packet;
4804 uint32_t packet_len;
4805 uint32_t pv;
4806
4807 /* suboption header - needs additional argument for it */
4808 if (*(args[cur_arg+1]) == 0) {
4809 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4810 file, linenum, args[0], args[1], args[cur_arg]);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
4814
4815 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4816 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4817 pv = htonl(0x30000); /* protocol version 3.0 */
4818
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004819 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004820
4821 memcpy(packet + 4, &pv, 4);
4822
4823 /* copy "user" */
4824 memcpy(packet + 8, "user", 4);
4825
4826 /* copy username */
4827 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4828
4829 free(curproxy->check_req);
4830 curproxy->check_req = packet;
4831 curproxy->check_len = packet_len;
4832
4833 packet_len = htonl(packet_len);
4834 memcpy(packet, &packet_len, 4);
4835 cur_arg += 2;
4836 } else {
4837 /* unknown suboption - catchall */
4838 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4839 file, linenum, args[0], args[1]);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
4843 } /* end while loop */
4844 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004845 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4846 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004847 }
4848
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004849 else if (!strcmp(args[1], "redis-check")) {
4850 /* use REDIS PING request to check servers' health */
4851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4852 err_code |= ERR_WARN;
4853
4854 free(curproxy->check_req);
4855 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004856 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004857 curproxy->options2 |= PR_O2_REDIS_CHK;
4858
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004859 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004860 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4861 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004862
4863 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4864 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004865 }
4866
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004867 else if (!strcmp(args[1], "mysql-check")) {
4868 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004869 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4870 err_code |= ERR_WARN;
4871
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004872 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;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004875 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004876
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004877 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004878 * const char mysql40_client_auth_pkt[] = {
4879 * "\x0e\x00\x00" // packet length
4880 * "\x01" // packet number
4881 * "\x00\x00" // client capabilities
4882 * "\x00\x00\x01" // max packet
4883 * "haproxy\x00" // username (null terminated string)
4884 * "\x00" // filler (always 0x00)
4885 * "\x01\x00\x00" // packet length
4886 * "\x00" // packet number
4887 * "\x01" // COM_QUIT command
4888 * };
4889 */
4890
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004891 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4892 * const char mysql41_client_auth_pkt[] = {
4893 * "\x0e\x00\x00\" // packet length
4894 * "\x01" // packet number
4895 * "\x00\x00\x00\x00" // client capabilities
4896 * "\x00\x00\x00\x01" // max packet
4897 * "\x21" // character set (UTF-8)
4898 * char[23] // All zeroes
4899 * "haproxy\x00" // username (null terminated string)
4900 * "\x00" // filler (always 0x00)
4901 * "\x01\x00\x00" // packet length
4902 * "\x00" // packet number
4903 * "\x01" // COM_QUIT command
4904 * };
4905 */
4906
4907
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004908 if (*(args[2])) {
4909 int cur_arg = 2;
4910
4911 while (*(args[cur_arg])) {
4912 if (strcmp(args[cur_arg], "user") == 0) {
4913 char *mysqluser;
4914 int packetlen, reqlen, userlen;
4915
4916 /* suboption header - needs additional argument for it */
4917 if (*(args[cur_arg+1]) == 0) {
4918 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4919 file, linenum, args[0], args[1], args[cur_arg]);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923 mysqluser = args[cur_arg + 1];
4924 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004925
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004926 if (*(args[cur_arg+2])) {
4927 if (!strcmp(args[cur_arg+2], "post-41")) {
4928 packetlen = userlen + 7 + 27;
4929 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004930
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004931 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004932 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004933 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004934
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004935 snprintf(curproxy->check_req, 4, "%c%c%c",
4936 ((unsigned char) packetlen & 0xff),
4937 ((unsigned char) (packetlen >> 8) & 0xff),
4938 ((unsigned char) (packetlen >> 16) & 0xff));
4939
4940 curproxy->check_req[3] = 1;
4941 curproxy->check_req[5] = 130;
4942 curproxy->check_req[11] = 1;
4943 curproxy->check_req[12] = 33;
4944 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4945 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4946 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4947 cur_arg += 3;
4948 } else {
4949 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953 } else {
4954 packetlen = userlen + 7;
4955 reqlen = packetlen + 9;
4956
4957 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004958 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004959 curproxy->check_len = reqlen;
4960
4961 snprintf(curproxy->check_req, 4, "%c%c%c",
4962 ((unsigned char) packetlen & 0xff),
4963 ((unsigned char) (packetlen >> 8) & 0xff),
4964 ((unsigned char) (packetlen >> 16) & 0xff));
4965
4966 curproxy->check_req[3] = 1;
4967 curproxy->check_req[5] = 128;
4968 curproxy->check_req[8] = 1;
4969 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4970 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4971 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4972 cur_arg += 2;
4973 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004974 } else {
4975 /* unknown suboption - catchall */
4976 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4977 file, linenum, args[0], args[1]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981 } /* end while loop */
4982 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004983 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004984 else if (!strcmp(args[1], "ldap-check")) {
4985 /* use LDAP request to check servers' health */
4986 free(curproxy->check_req);
4987 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004988 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004989 curproxy->options2 |= PR_O2_LDAP_CHK;
4990
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004991 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004992 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4993 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004994 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4995 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004996 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004997 else if (!strcmp(args[1], "spop-check")) {
4998 if (curproxy == &defproxy) {
4999 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5000 file, linenum, args[0], args[1]);
5001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
5004 if (curproxy->cap & PR_CAP_FE) {
5005 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5006 file, linenum, args[0], args[1]);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010
5011 /* use SPOE request to check servers' health */
5012 free(curproxy->check_req);
5013 curproxy->check_req = NULL;
5014 curproxy->options2 &= ~PR_O2_CHK_ANY;
5015 curproxy->options2 |= PR_O2_SPOP_CHK;
5016
Christopher Faulet8ef75252017-02-20 22:56:03 +01005017 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005018 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
5021 }
5022 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5023 goto out;
5024 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005025 else if (!strcmp(args[1], "tcp-check")) {
5026 /* use raw TCPCHK send/expect to check servers' health */
5027 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5028 err_code |= ERR_WARN;
5029
5030 free(curproxy->check_req);
5031 curproxy->check_req = NULL;
5032 curproxy->options2 &= ~PR_O2_CHK_ANY;
5033 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005034 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5035 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005036 }
Simon Horman98637e52014-06-20 12:30:16 +09005037 else if (!strcmp(args[1], "external-check")) {
5038 /* excute an external command to check servers' health */
5039 free(curproxy->check_req);
5040 curproxy->check_req = NULL;
5041 curproxy->options2 &= ~PR_O2_CHK_ANY;
5042 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005043 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5044 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005045 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005046 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005047 int cur_arg;
5048
5049 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5050 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005051 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005052
Willy Tarreau87cf5142011-08-19 22:57:24 +02005053 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005054
5055 free(curproxy->fwdfor_hdr_name);
5056 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5057 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5058
5059 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5060 cur_arg = 2;
5061 while (*(args[cur_arg])) {
5062 if (!strcmp(args[cur_arg], "except")) {
5063 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005064 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005065 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5066 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005069 }
5070 /* flush useless bits */
5071 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005072 cur_arg += 2;
5073 } else if (!strcmp(args[cur_arg], "header")) {
5074 /* suboption header - needs additional argument for it */
5075 if (*(args[cur_arg+1]) == 0) {
5076 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5077 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005080 }
5081 free(curproxy->fwdfor_hdr_name);
5082 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5083 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5084 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005085 } else if (!strcmp(args[cur_arg], "if-none")) {
5086 curproxy->options &= ~PR_O_FF_ALWAYS;
5087 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005088 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005089 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005090 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005091 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005094 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005095 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005096 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005097 else if (!strcmp(args[1], "originalto")) {
5098 int cur_arg;
5099
5100 /* insert x-original-to field, but not for the IP address listed as an except.
5101 * set default options (ie: bitfield, header name, etc)
5102 */
5103
5104 curproxy->options |= PR_O_ORGTO;
5105
5106 free(curproxy->orgto_hdr_name);
5107 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5108 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5109
Willy Tarreau87cf5142011-08-19 22:57:24 +02005110 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005111 cur_arg = 2;
5112 while (*(args[cur_arg])) {
5113 if (!strcmp(args[cur_arg], "except")) {
5114 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005115 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 +02005116 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5117 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005120 }
5121 /* flush useless bits */
5122 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5123 cur_arg += 2;
5124 } else if (!strcmp(args[cur_arg], "header")) {
5125 /* suboption header - needs additional argument for it */
5126 if (*(args[cur_arg+1]) == 0) {
5127 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5128 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005131 }
5132 free(curproxy->orgto_hdr_name);
5133 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5134 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5135 cur_arg += 2;
5136 } else {
5137 /* unknown suboption - catchall */
5138 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5139 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005142 }
5143 } /* end while loop */
5144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 else {
5146 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
Willy Tarreau93893792009-07-23 13:19:11 +02005150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005152 else if (!strcmp(args[0], "default_backend")) {
5153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005155
5156 if (*(args[1]) == 0) {
5157 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005160 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005161 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005162 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005163
5164 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5165 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005170
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005171 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5172 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 +01005173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 /* enable reconnections to dispatch */
5176 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005177
5178 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005181 else if (!strcmp(args[0], "http-reuse")) {
5182 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5183 err_code |= ERR_WARN;
5184
5185 if (strcmp(args[1], "never") == 0) {
5186 /* enable a graceful server shutdown on an HTTP 404 response */
5187 curproxy->options &= ~PR_O_REUSE_MASK;
5188 curproxy->options |= PR_O_REUSE_NEVR;
5189 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5190 goto out;
5191 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005192 else if (strcmp(args[1], "safe") == 0) {
5193 /* enable a graceful server shutdown on an HTTP 404 response */
5194 curproxy->options &= ~PR_O_REUSE_MASK;
5195 curproxy->options |= PR_O_REUSE_SAFE;
5196 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5197 goto out;
5198 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005199 else if (strcmp(args[1], "aggressive") == 0) {
5200 curproxy->options &= ~PR_O_REUSE_MASK;
5201 curproxy->options |= PR_O_REUSE_AGGR;
5202 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5203 goto out;
5204 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005205 else if (strcmp(args[1], "always") == 0) {
5206 /* enable a graceful server shutdown on an HTTP 404 response */
5207 curproxy->options &= ~PR_O_REUSE_MASK;
5208 curproxy->options |= PR_O_REUSE_ALWS;
5209 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5210 goto out;
5211 }
5212 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005213 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005218 else if (!strcmp(args[0], "http-check")) {
5219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005221
5222 if (strcmp(args[1], "disable-on-404") == 0) {
5223 /* enable a graceful server shutdown on an HTTP 404 response */
5224 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005225 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5226 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005227 }
Willy Tarreauef781042010-01-27 11:53:01 +01005228 else if (strcmp(args[1], "send-state") == 0) {
5229 /* enable emission of the apparent state of a server in HTTP checks */
5230 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005231 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5232 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005233 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005234 else if (strcmp(args[1], "expect") == 0) {
5235 const char *ptr_arg;
5236 int cur_arg;
5237
5238 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5239 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243
5244 cur_arg = 2;
5245 /* consider exclamation marks, sole or at the beginning of a word */
5246 while (*(ptr_arg = args[cur_arg])) {
5247 while (*ptr_arg == '!') {
5248 curproxy->options2 ^= PR_O2_EXP_INV;
5249 ptr_arg++;
5250 }
5251 if (*ptr_arg)
5252 break;
5253 cur_arg++;
5254 }
5255 /* now ptr_arg points to the beginning of a word past any possible
5256 * exclamation mark, and cur_arg is the argument which holds this word.
5257 */
5258 if (strcmp(ptr_arg, "status") == 0) {
5259 if (!*(args[cur_arg + 1])) {
5260 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5261 file, linenum, args[0], args[1], ptr_arg);
5262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005266 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005267 curproxy->expect_str = strdup(args[cur_arg + 1]);
5268 }
5269 else if (strcmp(ptr_arg, "string") == 0) {
5270 if (!*(args[cur_arg + 1])) {
5271 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5272 file, linenum, args[0], args[1], ptr_arg);
5273 err_code |= ERR_ALERT | ERR_FATAL;
5274 goto out;
5275 }
5276 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005277 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005278 curproxy->expect_str = strdup(args[cur_arg + 1]);
5279 }
5280 else if (strcmp(ptr_arg, "rstatus") == 0) {
5281 if (!*(args[cur_arg + 1])) {
5282 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5283 file, linenum, args[0], args[1], ptr_arg);
5284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
5286 }
5287 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005288 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005289 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005290 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005291 free(curproxy->expect_regex);
5292 curproxy->expect_regex = NULL;
5293 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005294 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005295 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5296 error = NULL;
5297 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5298 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5299 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5300 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304 }
5305 else if (strcmp(ptr_arg, "rstring") == 0) {
5306 if (!*(args[cur_arg + 1])) {
5307 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5308 file, linenum, args[0], args[1], ptr_arg);
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005313 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005314 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005315 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005316 free(curproxy->expect_regex);
5317 curproxy->expect_regex = NULL;
5318 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005319 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005320 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5321 error = NULL;
5322 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5323 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5324 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5325 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
5329 }
5330 else {
5331 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5332 file, linenum, args[0], args[1], ptr_arg);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005337 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005338 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 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005341 }
5342 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005343 else if (!strcmp(args[0], "tcp-check")) {
5344 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5345 err_code |= ERR_WARN;
5346
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005347 if (strcmp(args[1], "comment") == 0) {
5348 int cur_arg;
5349 struct tcpcheck_rule *tcpcheck;
5350
5351 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005352 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005353 tcpcheck->action = TCPCHK_ACT_COMMENT;
5354
5355 if (!*args[cur_arg + 1]) {
5356 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5357 file, linenum, args[cur_arg]);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361
5362 tcpcheck->comment = strdup(args[cur_arg + 1]);
5363
5364 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005365 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5366 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005367 }
5368 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005369 const char *ptr_arg;
5370 int cur_arg;
5371 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005372
5373 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005374 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5375 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5376 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5377 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5378 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005379
Willy Tarreau5581c272015-05-13 12:24:53 +02005380 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5381 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5382 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5383 file, linenum);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005386 }
5387
5388 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005389 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005390 tcpcheck->action = TCPCHK_ACT_CONNECT;
5391
5392 /* parsing each parameters to fill up the rule */
5393 while (*(ptr_arg = args[cur_arg])) {
5394 /* tcp port */
5395 if (strcmp(args[cur_arg], "port") == 0) {
5396 if ( (atol(args[cur_arg + 1]) > 65535) ||
5397 (atol(args[cur_arg + 1]) < 1) ){
5398 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5399 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403 tcpcheck->port = atol(args[cur_arg + 1]);
5404 cur_arg += 2;
5405 }
5406 /* send proxy protocol */
5407 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5408 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5409 cur_arg++;
5410 }
5411#ifdef USE_OPENSSL
5412 else if (strcmp(args[cur_arg], "ssl") == 0) {
5413 curproxy->options |= PR_O_TCPCHK_SSL;
5414 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5415 cur_arg++;
5416 }
5417#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005418 /* comment for this tcpcheck line */
5419 else if (strcmp(args[cur_arg], "comment") == 0) {
5420 if (!*args[cur_arg + 1]) {
5421 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5422 file, linenum, args[cur_arg]);
5423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
5425 }
5426 tcpcheck->comment = strdup(args[cur_arg + 1]);
5427 cur_arg += 2;
5428 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005429 else {
5430#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005431 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 +01005432#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005433 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 +01005434#endif /* USE_OPENSSL */
5435 file, linenum, args[0], args[1], args[cur_arg]);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439
5440 }
5441
5442 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5443 }
5444 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005445 if (! *(args[2]) ) {
5446 /* SEND string expected */
5447 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5448 file, linenum, args[0], args[1], args[2]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 } else {
5452 struct tcpcheck_rule *tcpcheck;
5453
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005454 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005455
5456 tcpcheck->action = TCPCHK_ACT_SEND;
5457 tcpcheck->string_len = strlen(args[2]);
5458 tcpcheck->string = strdup(args[2]);
5459 tcpcheck->expect_regex = NULL;
5460
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005461 /* comment for this tcpcheck line */
5462 if (strcmp(args[3], "comment") == 0) {
5463 if (!*args[4]) {
5464 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5465 file, linenum, args[3]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
5469 tcpcheck->comment = strdup(args[4]);
5470 }
5471
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005472 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5473 }
5474 }
5475 else if (strcmp(args[1], "send-binary") == 0) {
5476 if (! *(args[2]) ) {
5477 /* SEND binary string expected */
5478 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5479 file, linenum, args[0], args[1], args[2]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 } else {
5483 struct tcpcheck_rule *tcpcheck;
5484 char *err = NULL;
5485
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005486 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005487
5488 tcpcheck->action = TCPCHK_ACT_SEND;
5489 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5490 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5491 file, linenum, args[0], args[1], args[2], err);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495 tcpcheck->expect_regex = NULL;
5496
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005497 /* comment for this tcpcheck line */
5498 if (strcmp(args[3], "comment") == 0) {
5499 if (!*args[4]) {
5500 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5501 file, linenum, args[3]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
5505 tcpcheck->comment = strdup(args[4]);
5506 }
5507
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005508 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5509 }
5510 }
5511 else if (strcmp(args[1], "expect") == 0) {
5512 const char *ptr_arg;
5513 int cur_arg;
5514 int inverse = 0;
5515
5516 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5517 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521
5522 cur_arg = 2;
5523 /* consider exclamation marks, sole or at the beginning of a word */
5524 while (*(ptr_arg = args[cur_arg])) {
5525 while (*ptr_arg == '!') {
5526 inverse = !inverse;
5527 ptr_arg++;
5528 }
5529 if (*ptr_arg)
5530 break;
5531 cur_arg++;
5532 }
5533 /* now ptr_arg points to the beginning of a word past any possible
5534 * exclamation mark, and cur_arg is the argument which holds this word.
5535 */
5536 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005537 struct tcpcheck_rule *tcpcheck;
5538 char *err = NULL;
5539
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005540 if (!*(args[cur_arg + 1])) {
5541 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5542 file, linenum, args[0], args[1], ptr_arg);
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
5545 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005546
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005547 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005548
5549 tcpcheck->action = TCPCHK_ACT_EXPECT;
5550 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5551 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5552 file, linenum, args[0], args[1], args[2], err);
5553 err_code |= ERR_ALERT | ERR_FATAL;
5554 goto out;
5555 }
5556 tcpcheck->expect_regex = NULL;
5557 tcpcheck->inverse = inverse;
5558
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005559 /* tcpcheck comment */
5560 cur_arg += 2;
5561 if (strcmp(args[cur_arg], "comment") == 0) {
5562 if (!*args[cur_arg + 1]) {
5563 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5564 file, linenum, args[cur_arg + 1]);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
5568 tcpcheck->comment = strdup(args[cur_arg + 1]);
5569 }
5570
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005571 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5572 }
5573 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005574 struct tcpcheck_rule *tcpcheck;
5575
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005576 if (!*(args[cur_arg + 1])) {
5577 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5578 file, linenum, args[0], args[1], ptr_arg);
5579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
5581 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005582
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005583 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005584
5585 tcpcheck->action = TCPCHK_ACT_EXPECT;
5586 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5587 tcpcheck->string = strdup(args[cur_arg + 1]);
5588 tcpcheck->expect_regex = NULL;
5589 tcpcheck->inverse = inverse;
5590
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005591 /* tcpcheck comment */
5592 cur_arg += 2;
5593 if (strcmp(args[cur_arg], "comment") == 0) {
5594 if (!*args[cur_arg + 1]) {
5595 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5596 file, linenum, args[cur_arg + 1]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 tcpcheck->comment = strdup(args[cur_arg + 1]);
5601 }
5602
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005603 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5604 }
5605 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005606 struct tcpcheck_rule *tcpcheck;
5607
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005608 if (!*(args[cur_arg + 1])) {
5609 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5610 file, linenum, args[0], args[1], ptr_arg);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005614
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005615 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616
5617 tcpcheck->action = TCPCHK_ACT_EXPECT;
5618 tcpcheck->string_len = 0;
5619 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005620 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5621 error = NULL;
5622 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5623 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5624 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5625 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629 tcpcheck->inverse = inverse;
5630
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005631 /* tcpcheck comment */
5632 cur_arg += 2;
5633 if (strcmp(args[cur_arg], "comment") == 0) {
5634 if (!*args[cur_arg + 1]) {
5635 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5636 file, linenum, args[cur_arg + 1]);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640 tcpcheck->comment = strdup(args[cur_arg + 1]);
5641 }
5642
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005643 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5644 }
5645 else {
5646 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5647 file, linenum, args[0], args[1], ptr_arg);
5648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
5650 }
5651 }
5652 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005653 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005658 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005659 if (curproxy == &defproxy) {
5660 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005663 }
5664
Willy Tarreaub80c2302007-11-30 20:51:32 +01005665 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005666 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005667
5668 if (strcmp(args[1], "fail") == 0) {
5669 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005670 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005671 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005675 }
5676
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005677 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5678 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5679 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005682 }
5683 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5684 }
5685 else {
5686 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005689 }
5690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691#ifdef TPROXY
5692 else if (!strcmp(args[0], "transparent")) {
5693 /* enable transparent proxy connections */
5694 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005695 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 }
5698#endif
5699 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005700 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005701 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005702
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 if (*(args[1]) == 0) {
5704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 }
5708 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005712 else if (!strcmp(args[0], "backlog")) { /* backlog */
5713 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005715
5716 if (*(args[1]) == 0) {
5717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005720 }
5721 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005722 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5723 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005724 }
Willy Tarreau86034312006-12-29 00:10:33 +01005725 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005728
Willy Tarreau86034312006-12-29 00:10:33 +01005729 if (*(args[1]) == 0) {
5730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005733 }
5734 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5736 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5739 if (*(args[1]) == 0) {
5740 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005744 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5745 if (err) {
5746 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5747 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005750 }
5751 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005752 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 }
5755 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005756 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005757 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005758 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005759
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 if (curproxy == &defproxy) {
5761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005767
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005768 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005769 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005770 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005771 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005772 goto out;
5773 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005774
5775 proto = protocol_by_family(sk->ss_family);
5776 if (!proto || !proto->connect) {
5777 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5778 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
5781 }
5782
5783 if (port1 != port2) {
5784 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5785 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005789
5790 if (!port1) {
5791 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5792 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
5795 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005796
William Lallemanddf1425a2015-04-28 20:17:49 +02005797 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5798 goto out;
5799
Willy Tarreaud5191e72010-02-09 20:50:45 +01005800 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005801 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005804 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005805 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005806
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005807 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5808 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005813 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005814 /**
5815 * The syntax for hash-type config element is
5816 * hash-type {map-based|consistent} [[<algo>] avalanche]
5817 *
5818 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5819 */
5820 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005821
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5823 err_code |= ERR_WARN;
5824
5825 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005826 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5827 }
5828 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005829 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5830 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005831 else if (strcmp(args[1], "avalanche") == 0) {
5832 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]);
5833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005835 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005836 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005837 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005838 err_code |= ERR_ALERT | ERR_FATAL;
5839 goto out;
5840 }
Bhaskar98634f02013-10-29 23:30:51 -04005841
5842 /* set the hash function to use */
5843 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005845 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005846
5847 /* if consistent with no argument, then avalanche modifier is also applied */
5848 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5849 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005850 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005851 /* set the hash function */
5852 if (!strcmp(args[2], "sdbm")) {
5853 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5854 }
5855 else if (!strcmp(args[2], "djb2")) {
5856 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005857 }
5858 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005859 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005860 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005861 else if (!strcmp(args[2], "crc32")) {
5862 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5863 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005864 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005865 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 -05005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
5868 }
5869
5870 /* set the hash modifier */
5871 if (!strcmp(args[3], "avalanche")) {
5872 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5873 }
5874 else if (*args[3]) {
5875 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
5878 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005879 }
William Lallemanda73203e2012-03-12 12:48:57 +01005880 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005881 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5882 if (*(args[1]) == 0) {
5883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
5887 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5888 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5889 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5890 err_code |= ERR_ALERT | ERR_FATAL;
5891 goto out;
5892 }
5893 }
William Lallemanda73203e2012-03-12 12:48:57 +01005894 else if (strcmp(args[0], "unique-id-format") == 0) {
5895 if (!*(args[1])) {
5896 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
William Lallemand3203ff42012-11-11 17:30:56 +01005900 if (*(args[2])) {
5901 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
5904 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005905 free(curproxy->conf.uniqueid_format_string);
5906 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005907
Willy Tarreau62a61232013-04-12 18:13:46 +02005908 free(curproxy->conf.uif_file);
5909 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5910 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005911 }
William Lallemanda73203e2012-03-12 12:48:57 +01005912
5913 else if (strcmp(args[0], "unique-id-header") == 0) {
5914 if (!*(args[1])) {
5915 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
5918 }
5919 free(curproxy->header_unique_id);
5920 curproxy->header_unique_id = strdup(args[1]);
5921 }
5922
William Lallemand723b73a2012-02-08 16:37:49 +01005923 else if (strcmp(args[0], "log-format") == 0) {
5924 if (!*(args[1])) {
5925 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
5928 }
William Lallemand3203ff42012-11-11 17:30:56 +01005929 if (*(args[2])) {
5930 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5931 err_code |= ERR_ALERT | ERR_FATAL;
5932 goto out;
5933 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005934 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5935 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005936
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005937 if (curproxy->conf.logformat_string == default_http_log_format)
5938 oldlogformat = "option httplog";
5939 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5940 oldlogformat = "option tcplog";
5941 else if (curproxy->conf.logformat_string == clf_http_log_format)
5942 oldlogformat = "option httplog clf";
5943 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5944 file, linenum, oldlogformat);
5945 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005946 if (curproxy->conf.logformat_string != default_http_log_format &&
5947 curproxy->conf.logformat_string != default_tcp_log_format &&
5948 curproxy->conf.logformat_string != clf_http_log_format)
5949 free(curproxy->conf.logformat_string);
5950 curproxy->conf.logformat_string = strdup(args[1]);
5951
5952 free(curproxy->conf.lfs_file);
5953 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5954 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005955
5956 /* get a chance to improve log-format error reporting by
5957 * reporting the correct line-number when possible.
5958 */
5959 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5960 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5961 file, linenum, curproxy->id);
5962 err_code |= ERR_WARN;
5963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005965 else if (!strcmp(args[0], "log-format-sd")) {
5966 if (!*(args[1])) {
5967 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5968 err_code |= ERR_ALERT | ERR_FATAL;
5969 goto out;
5970 }
5971 if (*(args[2])) {
5972 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5973 err_code |= ERR_ALERT | ERR_FATAL;
5974 goto out;
5975 }
5976
5977 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5978 free(curproxy->conf.logformat_sd_string);
5979 curproxy->conf.logformat_sd_string = strdup(args[1]);
5980
5981 free(curproxy->conf.lfsd_file);
5982 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5983 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5984
5985 /* get a chance to improve log-format-sd error reporting by
5986 * reporting the correct line-number when possible.
5987 */
5988 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5989 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5990 file, linenum, curproxy->id);
5991 err_code |= ERR_WARN;
5992 }
5993 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005994 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5995 if (*(args[1]) == 0) {
5996 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006000 chunk_destroy(&curproxy->log_tag);
6001 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006002 }
William Lallemand0f99e342011-10-12 17:50:54 +02006003 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6004 /* delete previous herited or defined syslog servers */
6005 struct logsrv *back;
6006
6007 if (*(args[1]) != 0) {
6008 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
6011 }
6012
William Lallemand723b73a2012-02-08 16:37:49 +01006013 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6014 LIST_DEL(&tmplogsrv->list);
6015 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006016 }
6017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006019 struct logsrv *logsrv;
6020
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006022 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006023 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006024 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006025 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006026 LIST_INIT(&node->list);
6027 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 }
6030 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006031 struct sockaddr_storage *sk;
6032 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006033 int arg = 0;
6034 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006035
Vincent Bernat02779b62016-04-03 13:48:43 +02006036 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037
Willy Tarreau18324f52014-06-27 18:10:07 +02006038 /* just after the address, a length may be specified */
6039 if (strcmp(args[arg+2], "len") == 0) {
6040 len = atoi(args[arg+3]);
6041 if (len < 80 || len > 65535) {
6042 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6043 file, linenum, args[arg+3]);
6044 err_code |= ERR_ALERT | ERR_FATAL;
6045 goto out;
6046 }
6047 logsrv->maxlen = len;
6048
6049 /* skip these two args */
6050 arg += 2;
6051 }
6052 else
6053 logsrv->maxlen = MAX_SYSLOG_LEN;
6054
6055 if (logsrv->maxlen > global.max_syslog_len) {
6056 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006057 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6058 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6059 logline = my_realloc2(logline, global.max_syslog_len + 1);
6060 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006061 }
6062
Dragan Dosen1322d092015-09-22 16:05:32 +02006063 /* after the length, a format may be specified */
6064 if (strcmp(args[arg+2], "format") == 0) {
6065 logsrv->format = get_log_format(args[arg+3]);
6066 if (logsrv->format < 0) {
6067 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
6071
6072 /* skip these two args */
6073 arg += 2;
6074 }
6075
William Lallemanddf1425a2015-04-28 20:17:49 +02006076 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6077 goto out;
6078
Willy Tarreau18324f52014-06-27 18:10:07 +02006079 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006080 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006081 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
6084
Willy Tarreaubaaee002006-06-26 02:48:02 +02006085 }
6086
William Lallemand0f99e342011-10-12 17:50:54 +02006087 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006088 if (*(args[arg+3])) {
6089 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006090 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006091 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006092 err_code |= ERR_ALERT | ERR_FATAL;
6093 goto out;
6094
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
6096 }
6097
William Lallemand0f99e342011-10-12 17:50:54 +02006098 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006099 if (*(args[arg+4])) {
6100 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006101 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006102 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006103 err_code |= ERR_ALERT | ERR_FATAL;
6104 goto out;
6105
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006106 }
6107 }
6108
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006109 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006110 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006111 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006113 goto out;
6114 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006115
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006116 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006117
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006118 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006119 if (port1 != port2) {
6120 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6121 file, linenum, args[0], args[1]);
6122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124 }
6125
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006126 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006127 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 }
William Lallemand0f99e342011-10-12 17:50:54 +02006129
6130 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 }
6132 else {
6133 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6134 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 }
6138 }
6139 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006140 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006141 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006142 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006143 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006144
Willy Tarreau977b8e42006-12-29 14:19:17 +01006145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006147
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006149 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6150 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006154
6155 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006156 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6157 free(curproxy->conn_src.iface_name);
6158 curproxy->conn_src.iface_name = NULL;
6159 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006160
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006161 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006162 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006163 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006164 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006165 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006166 goto out;
6167 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006168
6169 proto = protocol_by_family(sk->ss_family);
6170 if (!proto || !proto->connect) {
6171 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006172 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006173 err_code |= ERR_ALERT | ERR_FATAL;
6174 goto out;
6175 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006176
6177 if (port1 != port2) {
6178 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6179 file, linenum, args[0], args[1]);
6180 err_code |= ERR_ALERT | ERR_FATAL;
6181 goto out;
6182 }
6183
Willy Tarreauef9a3602012-12-08 22:29:20 +01006184 curproxy->conn_src.source_addr = *sk;
6185 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006186
6187 cur_arg = 2;
6188 while (*(args[cur_arg])) {
6189 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006190#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006191 if (!*args[cur_arg + 1]) {
6192 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6193 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006194 err_code |= ERR_ALERT | ERR_FATAL;
6195 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006196 }
6197
6198 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006199 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6200 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006201 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006202 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6203 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006204 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6205 char *name, *end;
6206
6207 name = args[cur_arg+1] + 7;
6208 while (isspace(*name))
6209 name++;
6210
6211 end = name;
6212 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6213 end++;
6214
Willy Tarreauef9a3602012-12-08 22:29:20 +01006215 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6216 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6217 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6218 curproxy->conn_src.bind_hdr_len = end - name;
6219 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6220 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6221 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006222
6223 /* now look for an occurrence number */
6224 while (isspace(*end))
6225 end++;
6226 if (*end == ',') {
6227 end++;
6228 name = end;
6229 if (*end == '-')
6230 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006231 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006232 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006233 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006234 }
6235
Willy Tarreauef9a3602012-12-08 22:29:20 +01006236 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006237 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6238 " occurrences values smaller than %d.\n",
6239 file, linenum, MAX_HDR_HISTORY);
6240 err_code |= ERR_ALERT | ERR_FATAL;
6241 goto out;
6242 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006243 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006244 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006245
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006246 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006247 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006248 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006249 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006250 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006251 goto out;
6252 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006253
6254 proto = protocol_by_family(sk->ss_family);
6255 if (!proto || !proto->connect) {
6256 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6257 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006258 err_code |= ERR_ALERT | ERR_FATAL;
6259 goto out;
6260 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006261
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006262 if (port1 != port2) {
6263 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6264 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
6267 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006268 curproxy->conn_src.tproxy_addr = *sk;
6269 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006270 }
6271 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006272#else /* no TPROXY support */
6273 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006274 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006275 err_code |= ERR_ALERT | ERR_FATAL;
6276 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006277#endif
6278 cur_arg += 2;
6279 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006280 }
6281
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006282 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6283#ifdef SO_BINDTODEVICE
6284 if (!*args[cur_arg + 1]) {
6285 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006289 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006290 free(curproxy->conn_src.iface_name);
6291 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6292 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006293 global.last_checks |= LSTCHK_NETADM;
6294#else
6295 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6296 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006297 err_code |= ERR_ALERT | ERR_FATAL;
6298 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006299#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300 cur_arg += 2;
6301 continue;
6302 }
6303 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006304 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006309 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6310 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6311 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006316 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6318 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006319 err_code |= ERR_ALERT | ERR_FATAL;
6320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006322
6323 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006324 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006325 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006326 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 }
6329 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006330 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006331 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006332 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006333 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 }
6336 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006338 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006339 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 }
6343 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006345 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 }
6350 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006352 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006353 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006357 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6367 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006368 err_code |= ERR_ALERT | ERR_FATAL;
6369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371
6372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006374 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
6378 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006380 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006381 args[0], args[1], NULL, (const char **)args+2);
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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_DENY, REG_ICASE,
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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, REG_ICASE,
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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_ALLOW, REG_ICASE,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006406 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
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_TARPIT, REG_ICASE,
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 Tarreaub8750a82006-09-03 09:56:00 +02006412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006414 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006415
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 if (curproxy == &defproxy) {
6417 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006421 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006422 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423
Willy Tarreaubaaee002006-06-26 02:48:02 +02006424 if (*(args[1]) == 0) {
6425 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006426 err_code |= ERR_ALERT | ERR_FATAL;
6427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006429
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006430 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006431 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6432 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6433 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006434 err_code |= ERR_ALERT | ERR_FATAL;
6435 goto out;
6436 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006437 err_code |= warnif_cond_conflicts(cond,
6438 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6439 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006440 }
6441 else if (*args[2]) {
6442 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6443 file, linenum, args[0], args[2]);
6444 err_code |= ERR_ALERT | ERR_FATAL;
6445 goto out;
6446 }
6447
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006448 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006449 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006450 wl->s = strdup(args[1]);
6451 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006452 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
6454 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6457 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006458 err_code |= ERR_ALERT | ERR_FATAL;
6459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006461
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006463 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006464 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
6468 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006470 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006471 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 }
6475 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006476 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006477 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006478 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
6489
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006492 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006498 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006499 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 }
6503 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006505 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006511 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006512
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 if (curproxy == &defproxy) {
6514 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006515 err_code |= ERR_ALERT | ERR_FATAL;
6516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006518 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006519 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521 if (*(args[1]) == 0) {
6522 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006523 err_code |= ERR_ALERT | ERR_FATAL;
6524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525 }
6526
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006527 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006528 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6529 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6530 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006531 err_code |= ERR_ALERT | ERR_FATAL;
6532 goto out;
6533 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006534 err_code |= warnif_cond_conflicts(cond,
6535 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6536 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006537 }
6538 else if (*args[2]) {
6539 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6540 file, linenum, args[0], args[2]);
6541 err_code |= ERR_ALERT | ERR_FATAL;
6542 goto out;
6543 }
6544
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006545 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006546 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006547 wl->s = strdup(args[1]);
6548 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 }
6550 else if (!strcmp(args[0], "errorloc") ||
6551 !strcmp(args[0], "errorloc302") ||
6552 !strcmp(args[0], "errorloc303")) { /* error location */
6553 int errnum, errlen;
6554 char *err;
6555
Willy Tarreau977b8e42006-12-29 14:19:17 +01006556 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006557 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006558
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006560 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006563 }
6564
6565 errnum = atol(args[1]);
6566 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006567 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6568 err = malloc(errlen);
6569 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006571 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6572 err = malloc(errlen);
6573 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574 }
6575
Willy Tarreau0f772532006-12-23 20:51:41 +01006576 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6577 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006578 chunk_destroy(&curproxy->errmsg[rc]);
6579 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006580 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006583
6584 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006585 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6586 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 free(err);
6588 }
6589 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006590 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6591 int errnum, errlen, fd;
6592 char *err;
6593 struct stat stat;
6594
6595 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006596 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006597
6598 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006599 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006600 err_code |= ERR_ALERT | ERR_FATAL;
6601 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006602 }
6603
6604 fd = open(args[2], O_RDONLY);
6605 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6606 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6607 file, linenum, args[2], args[1]);
6608 if (fd >= 0)
6609 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006610 err_code |= ERR_ALERT | ERR_FATAL;
6611 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006612 }
6613
Willy Tarreau27a674e2009-08-17 07:23:33 +02006614 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615 errlen = stat.st_size;
6616 } else {
6617 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006618 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006619 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006620 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006621 }
6622
6623 err = malloc(errlen); /* malloc() must succeed during parsing */
6624 errnum = read(fd, err, errlen);
6625 if (errnum != errlen) {
6626 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6627 file, linenum, args[2], args[1]);
6628 close(fd);
6629 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006630 err_code |= ERR_ALERT | ERR_FATAL;
6631 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006632 }
6633 close(fd);
6634
6635 errnum = atol(args[1]);
6636 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6637 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006638 chunk_destroy(&curproxy->errmsg[rc]);
6639 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006640 break;
6641 }
6642 }
6643
6644 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006645 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6646 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006647 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006648 free(err);
6649 }
6650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006651 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006652 struct cfg_kw_list *kwl;
6653 int index;
6654
6655 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6656 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6657 if (kwl->kw[index].section != CFG_LISTEN)
6658 continue;
6659 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6660 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006661 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006662 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006663 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006664 err_code |= ERR_ALERT | ERR_FATAL;
6665 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006666 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006667 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006668 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006669 err_code |= ERR_WARN;
6670 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006671 }
Willy Tarreau93893792009-07-23 13:19:11 +02006672 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006673 }
6674 }
6675 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006676
Willy Tarreau6daf3432008-01-22 16:44:08 +01006677 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006678 err_code |= ERR_ALERT | ERR_FATAL;
6679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680 }
Willy Tarreau93893792009-07-23 13:19:11 +02006681 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006682 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006683 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006684}
6685
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006686int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006687cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6688{
6689#ifdef CONFIG_HAP_NS
6690 const char *err;
6691 const char *item = args[0];
6692
6693 if (!strcmp(item, "namespace_list")) {
6694 return 0;
6695 }
6696 else if (!strcmp(item, "namespace")) {
6697 size_t idx = 1;
6698 const char *current;
6699 while (*(current = args[idx++])) {
6700 err = invalid_char(current);
6701 if (err) {
6702 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6703 file, linenum, *err, item, current);
6704 return ERR_ALERT | ERR_FATAL;
6705 }
6706
6707 if (netns_store_lookup(current, strlen(current))) {
6708 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6709 file, linenum, current);
6710 return ERR_ALERT | ERR_FATAL;
6711 }
6712 if (!netns_store_insert(current)) {
6713 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6714 file, linenum, current);
6715 return ERR_ALERT | ERR_FATAL;
6716 }
6717 }
6718 }
6719
6720 return 0;
6721#else
6722 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6723 file, linenum);
6724 return ERR_ALERT | ERR_FATAL;
6725#endif
6726}
6727
6728int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006729cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6730{
6731
6732 int err_code = 0;
6733 const char *err;
6734
6735 if (!strcmp(args[0], "userlist")) { /* new userlist */
6736 struct userlist *newul;
6737
6738 if (!*args[1]) {
6739 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6740 file, linenum, args[0]);
6741 err_code |= ERR_ALERT | ERR_FATAL;
6742 goto out;
6743 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006744 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6745 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006746
6747 err = invalid_char(args[1]);
6748 if (err) {
6749 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6750 file, linenum, *err, args[0], args[1]);
6751 err_code |= ERR_ALERT | ERR_FATAL;
6752 goto out;
6753 }
6754
6755 for (newul = userlist; newul; newul = newul->next)
6756 if (!strcmp(newul->name, args[1])) {
6757 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6758 file, linenum, args[1]);
6759 err_code |= ERR_WARN;
6760 goto out;
6761 }
6762
Vincent Bernat02779b62016-04-03 13:48:43 +02006763 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006764 if (!newul) {
6765 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6766 err_code |= ERR_ALERT | ERR_ABORT;
6767 goto out;
6768 }
6769
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006771 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6773 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006774 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775 goto out;
6776 }
6777
6778 newul->next = userlist;
6779 userlist = newul;
6780
6781 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006782 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006784 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006785
6786 if (!*args[1]) {
6787 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6788 file, linenum, args[0]);
6789 err_code |= ERR_ALERT | ERR_FATAL;
6790 goto out;
6791 }
6792
6793 err = invalid_char(args[1]);
6794 if (err) {
6795 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6796 file, linenum, *err, args[0], args[1]);
6797 err_code |= ERR_ALERT | ERR_FATAL;
6798 goto out;
6799 }
6800
William Lallemand4ac9f542015-05-28 18:03:51 +02006801 if (!userlist)
6802 goto out;
6803
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006804 for (ag = userlist->groups; ag; ag = ag->next)
6805 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006806 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6807 file, linenum, args[1], userlist->name);
6808 err_code |= ERR_ALERT;
6809 goto out;
6810 }
6811
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 ag = calloc(1, sizeof(*ag));
6813 if (!ag) {
6814 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6815 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006816 goto out;
6817 }
6818
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006819 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006820 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006821 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6822 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006823 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006824 goto out;
6825 }
6826
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006827 cur_arg = 2;
6828
6829 while (*args[cur_arg]) {
6830 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006831 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006832 cur_arg += 2;
6833 continue;
6834 } else {
6835 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6836 file, linenum, args[0]);
6837 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006838 free(ag->groupusers);
6839 free(ag->name);
6840 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006841 goto out;
6842 }
6843 }
6844
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006845 ag->next = userlist->groups;
6846 userlist->groups = ag;
6847
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006848 } else if (!strcmp(args[0], "user")) { /* new user */
6849 struct auth_users *newuser;
6850 int cur_arg;
6851
6852 if (!*args[1]) {
6853 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6854 file, linenum, args[0]);
6855 err_code |= ERR_ALERT | ERR_FATAL;
6856 goto out;
6857 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006858 if (!userlist)
6859 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860
6861 for (newuser = userlist->users; newuser; newuser = newuser->next)
6862 if (!strcmp(newuser->user, args[1])) {
6863 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6864 file, linenum, args[1], userlist->name);
6865 err_code |= ERR_ALERT;
6866 goto out;
6867 }
6868
Vincent Bernat02779b62016-04-03 13:48:43 +02006869 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870 if (!newuser) {
6871 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6872 err_code |= ERR_ALERT | ERR_ABORT;
6873 goto out;
6874 }
6875
6876 newuser->user = strdup(args[1]);
6877
6878 newuser->next = userlist->users;
6879 userlist->users = newuser;
6880
6881 cur_arg = 2;
6882
6883 while (*args[cur_arg]) {
6884 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006885#ifdef CONFIG_HAP_CRYPT
6886 if (!crypt("", args[cur_arg + 1])) {
6887 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6888 file, linenum, newuser->user);
6889 err_code |= ERR_ALERT | ERR_FATAL;
6890 goto out;
6891 }
6892#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006893 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6894 file, linenum);
6895 err_code |= ERR_ALERT;
6896#endif
6897 newuser->pass = strdup(args[cur_arg + 1]);
6898 cur_arg += 2;
6899 continue;
6900 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6901 newuser->pass = strdup(args[cur_arg + 1]);
6902 newuser->flags |= AU_O_INSECURE;
6903 cur_arg += 2;
6904 continue;
6905 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006906 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006907 cur_arg += 2;
6908 continue;
6909 } else {
6910 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6911 file, linenum, args[0]);
6912 err_code |= ERR_ALERT | ERR_FATAL;
6913 goto out;
6914 }
6915 }
6916 } else {
6917 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6918 err_code |= ERR_ALERT | ERR_FATAL;
6919 }
6920
6921out:
6922 return err_code;
6923}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006924
Christopher Faulet79bdef32016-11-04 22:36:15 +01006925int
6926cfg_parse_scope(const char *file, int linenum, char *line)
6927{
6928 char *beg, *end, *scope = NULL;
6929 int err_code = 0;
6930 const char *err;
6931
6932 beg = line + 1;
6933 end = strchr(beg, ']');
6934
6935 /* Detect end of scope declaration */
6936 if (!end || end == beg) {
6937 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6938 file, linenum);
6939 err_code |= ERR_ALERT | ERR_FATAL;
6940 goto out;
6941 }
6942
6943 /* Get scope name and check its validity */
6944 scope = my_strndup(beg, end-beg);
6945 err = invalid_char(scope);
6946 if (err) {
6947 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6948 file, linenum, *err);
6949 err_code |= ERR_ALERT | ERR_ABORT;
6950 goto out;
6951 }
6952
6953 /* Be sure to have a scope declaration alone on its line */
6954 line = end+1;
6955 while (isspace((unsigned char)*line))
6956 line++;
6957 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6958 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6959 file, linenum, *line);
6960 err_code |= ERR_ALERT | ERR_ABORT;
6961 goto out;
6962 }
6963
6964 /* We have a valid scope declaration, save it */
6965 free(cfg_scope);
6966 cfg_scope = scope;
6967 scope = NULL;
6968
6969 out:
6970 free(scope);
6971 return err_code;
6972}
6973
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974/*
6975 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006976 * Returns the error code, 0 if OK, or any combination of :
6977 * - ERR_ABORT: must abort ASAP
6978 * - ERR_FATAL: we can continue parsing but not start the service
6979 * - ERR_WARN: a warning has been emitted
6980 * - ERR_ALERT: an alert has been emitted
6981 * Only the two first ones can stop processing, the two others are just
6982 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006984int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006985{
William Lallemand64e84512015-05-12 14:25:37 +02006986 char *thisline;
6987 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988 FILE *f;
6989 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006990 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006991 struct cfg_section *cs = NULL;
6992 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006993 int readbytes = 0;
6994
6995 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006996 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006997 return -1;
6998 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006999
David Carlier97880bb2016-04-08 10:35:26 +01007000 if ((f=fopen(file,"r")) == NULL) {
7001 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004
William Lallemandb2f07452015-05-12 14:27:13 +02007005next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007006 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007007 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007008 char *end;
7009 char *args[MAX_LINE_ARGS + 1];
7010 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007011 int dquote = 0; /* double quote */
7012 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007013
Willy Tarreaubaaee002006-06-26 02:48:02 +02007014 linenum++;
7015
7016 end = line + strlen(line);
7017
William Lallemand64e84512015-05-12 14:25:37 +02007018 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007019 /* Check if we reached the limit and the last char is not \n.
7020 * Watch out for the last line without the terminating '\n'!
7021 */
William Lallemand64e84512015-05-12 14:25:37 +02007022 char *newline;
7023 int newlinesize = linesize * 2;
7024
7025 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7026 if (newline == NULL) {
7027 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7028 file, linenum);
7029 err_code |= ERR_ALERT | ERR_FATAL;
7030 continue;
7031 }
7032
7033 readbytes = linesize - 1;
7034 linesize = newlinesize;
7035 thisline = newline;
7036 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007037 }
7038
William Lallemand64e84512015-05-12 14:25:37 +02007039 readbytes = 0;
7040
Willy Tarreaubaaee002006-06-26 02:48:02 +02007041 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007042 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007044
Christopher Faulet79bdef32016-11-04 22:36:15 +01007045
7046 if (*line == '[') {/* This is the begining if a scope */
7047 err_code |= cfg_parse_scope(file, linenum, line);
7048 goto next_line;
7049 }
7050
Willy Tarreaubaaee002006-06-26 02:48:02 +02007051 arg = 0;
7052 args[arg] = line;
7053
7054 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007055 if (*line == '"' && !squote) { /* double quote outside single quotes */
7056 if (dquote)
7057 dquote = 0;
7058 else
7059 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007060 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007061 end--;
7062 }
7063 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7064 if (squote)
7065 squote = 0;
7066 else
7067 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007068 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007069 end--;
7070 }
7071 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7073 * C equivalent value. Other combinations left unchanged (eg: \1).
7074 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007075 int skip = 0;
7076 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7077 *line = line[1];
7078 skip = 1;
7079 }
7080 else if (line[1] == 'r') {
7081 *line = '\r';
7082 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007083 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007084 else if (line[1] == 'n') {
7085 *line = '\n';
7086 skip = 1;
7087 }
7088 else if (line[1] == 't') {
7089 *line = '\t';
7090 skip = 1;
7091 }
7092 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007093 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007094 unsigned char hex1, hex2;
7095 hex1 = toupper(line[2]) - '0';
7096 hex2 = toupper(line[3]) - '0';
7097 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7098 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7099 *line = (hex1<<4) + hex2;
7100 skip = 3;
7101 }
7102 else {
7103 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007104 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007105 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007106 } else if (line[1] == '"') {
7107 *line = '"';
7108 skip = 1;
7109 } else if (line[1] == '\'') {
7110 *line = '\'';
7111 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007112 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7113 *line = '$';
7114 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007115 }
7116 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007117 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007118 end -= skip;
7119 }
7120 line++;
7121 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007122 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 /* end of string, end of loop */
7124 *line = 0;
7125 break;
7126 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007127 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007129 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007130 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007131 line++;
7132 args[++arg] = line;
7133 }
William Lallemandb2f07452015-05-12 14:27:13 +02007134 else if (dquote && *line == '$') {
7135 /* environment variables are evaluated inside double quotes */
7136 char *var_beg;
7137 char *var_end;
7138 char save_char;
7139 char *value;
7140 int val_len;
7141 int newlinesize;
7142 int braces = 0;
7143
7144 var_beg = line + 1;
7145 var_end = var_beg;
7146
7147 if (*var_beg == '{') {
7148 var_beg++;
7149 var_end++;
7150 braces = 1;
7151 }
7152
7153 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7154 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7155 err_code |= ERR_ALERT | ERR_FATAL;
7156 goto next_line; /* skip current line */
7157 }
7158
7159 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7160 var_end++;
7161
7162 save_char = *var_end;
7163 *var_end = '\0';
7164 value = getenv(var_beg);
7165 *var_end = save_char;
7166 val_len = value ? strlen(value) : 0;
7167
7168 if (braces) {
7169 if (*var_end == '}') {
7170 var_end++;
7171 braces = 0;
7172 } else {
7173 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7174 err_code |= ERR_ALERT | ERR_FATAL;
7175 goto next_line; /* skip current line */
7176 }
7177 }
7178
7179 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7180
7181 /* if not enough space in thisline */
7182 if (newlinesize > linesize) {
7183 char *newline;
7184
7185 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7186 if (newline == NULL) {
7187 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7188 err_code |= ERR_ALERT | ERR_FATAL;
7189 goto next_line; /* slip current line */
7190 }
7191 /* recompute pointers if realloc returns a new pointer */
7192 if (newline != thisline) {
7193 int i;
7194 int diff;
7195
7196 for (i = 0; i <= arg; i++) {
7197 diff = args[i] - thisline;
7198 args[i] = newline + diff;
7199 }
7200
7201 diff = var_end - thisline;
7202 var_end = newline + diff;
7203 diff = end - thisline;
7204 end = newline + diff;
7205 diff = line - thisline;
7206 line = newline + diff;
7207 thisline = newline;
7208 }
7209 linesize = newlinesize;
7210 }
7211
7212 /* insert value inside the line */
7213 memmove(line + val_len, var_end, end - var_end + 1);
7214 memcpy(line, value, val_len);
7215 end += val_len - (var_end - line);
7216 line += val_len;
7217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218 else {
7219 line++;
7220 }
7221 }
William Lallemandb2f07452015-05-12 14:27:13 +02007222
William Lallemandf9873ba2015-05-05 17:37:14 +02007223 if (dquote) {
7224 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7225 err_code |= ERR_ALERT | ERR_FATAL;
7226 }
7227
7228 if (squote) {
7229 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7230 err_code |= ERR_ALERT | ERR_FATAL;
7231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007232
7233 /* empty line */
7234 if (!**args)
7235 continue;
7236
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007237 if (*line) {
7238 /* we had to stop due to too many args.
7239 * Let's terminate the string, print the offending part then cut the
7240 * last arg.
7241 */
7242 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7243 line++;
7244 *line = '\0';
7245
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007246 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007247 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007248 err_code |= ERR_ALERT | ERR_FATAL;
7249 args[arg] = line;
7250 }
7251
Willy Tarreau540abe42007-05-02 20:50:16 +02007252 /* zero out remaining args and ensure that at least one entry
7253 * is zeroed out.
7254 */
7255 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256 args[arg] = line;
7257 }
7258
Willy Tarreau3842f002009-06-14 11:39:52 +02007259 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007260 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007261 char *tmp;
7262
Willy Tarreau3842f002009-06-14 11:39:52 +02007263 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007264 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007265 for (arg=0; *args[arg+1]; arg++)
7266 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007267 *tmp = '\0'; // fix the next arg to \0
7268 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007269 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007270 else if (!strcmp(args[0], "default")) {
7271 kwm = KWM_DEF;
7272 for (arg=0; *args[arg+1]; arg++)
7273 args[arg] = args[arg+1]; // shift args after inversion
7274 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007275
William Lallemand0f99e342011-10-12 17:50:54 +02007276 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7277 strcmp(args[0], "log") != 0) {
7278 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007279 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007280 }
7281
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007282 /* detect section start */
7283 list_for_each_entry(ics, &sections, list) {
7284 if (strcmp(args[0], ics->section_name) == 0) {
7285 cursection = ics->section_name;
7286 cs = ics;
7287 break;
7288 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007289 }
7290
Willy Tarreaubaaee002006-06-26 02:48:02 +02007291 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007292 if (cs)
7293 err_code |= cs->section_parser(file, linenum, args, kwm);
7294 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007295 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007297 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007298
7299 if (err_code & ERR_ABORT)
7300 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007301 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007302 free(cfg_scope);
7303 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007304 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007305 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007306 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007307 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007308}
7309
Willy Tarreau64ab6072014-09-16 12:17:36 +02007310/* This function propagates processes from frontend <from> to backend <to> so
7311 * that it is always guaranteed that a backend pointed to by a frontend is
7312 * bound to all of its processes. After that, if the target is a "listen"
7313 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007314 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007315 * checked first to ensure that <to> is already bound to all processes of
7316 * <from>, there is no risk of looping and we ensure to follow the shortest
7317 * path to the destination.
7318 *
7319 * It is possible to set <to> to NULL for the first call so that the function
7320 * takes care of visiting the initial frontend in <from>.
7321 *
7322 * It is important to note that the function relies on the fact that all names
7323 * have already been resolved.
7324 */
7325void propagate_processes(struct proxy *from, struct proxy *to)
7326{
7327 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007328
7329 if (to) {
7330 /* check whether we need to go down */
7331 if (from->bind_proc &&
7332 (from->bind_proc & to->bind_proc) == from->bind_proc)
7333 return;
7334
7335 if (!from->bind_proc && !to->bind_proc)
7336 return;
7337
7338 to->bind_proc = from->bind_proc ?
7339 (to->bind_proc | from->bind_proc) : 0;
7340
7341 /* now propagate down */
7342 from = to;
7343 }
7344
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007345 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007346 return;
7347
Willy Tarreauf6b70012014-12-18 14:00:43 +01007348 if (from->state == PR_STSTOPPED)
7349 return;
7350
Willy Tarreau64ab6072014-09-16 12:17:36 +02007351 /* default_backend */
7352 if (from->defbe.be)
7353 propagate_processes(from, from->defbe.be);
7354
7355 /* use_backend */
7356 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007357 if (rule->dynamic)
7358 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007359 to = rule->be.backend;
7360 propagate_processes(from, to);
7361 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007362}
7363
Willy Tarreaubb925012009-07-23 13:36:36 +02007364/*
7365 * Returns the error code, 0 if OK, or any combination of :
7366 * - ERR_ABORT: must abort ASAP
7367 * - ERR_FATAL: we can continue parsing but not start the service
7368 * - ERR_WARN: a warning has been emitted
7369 * - ERR_ALERT: an alert has been emitted
7370 * Only the two first ones can stop processing, the two others are just
7371 * indicators.
7372 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007373int check_config_validity()
7374{
7375 int cfgerr = 0;
7376 struct proxy *curproxy = NULL;
7377 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007378 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007379 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007380 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007381 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007382 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007383
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007384 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007385 /*
7386 * Now, check for the integrity of all that we have collected.
7387 */
7388
7389 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007390 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007391
Willy Tarreau193b8c62012-11-22 00:17:38 +01007392 if (!global.tune.max_http_hdr)
7393 global.tune.max_http_hdr = MAX_HTTP_HDR;
7394
7395 if (!global.tune.cookie_len)
7396 global.tune.cookie_len = CAPTURE_LEN;
7397
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007398 if (!global.tune.requri_len)
7399 global.tune.requri_len = REQURI_LEN;
7400
Willy Tarreau193b8c62012-11-22 00:17:38 +01007401 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7402
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007403 /* allocate pool of resolution per resolvers */
7404 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7405 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7406 /* error message is already displayed by dns_alloc_resolution_pool() */
7407 err_code |= ERR_ALERT | ERR_ABORT;
7408 goto out;
7409 }
7410 }
7411
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007412 /* Post initialisation of the users and groups lists. */
7413 err_code = userlist_postinit();
7414 if (err_code != ERR_NONE)
7415 goto out;
7416
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007417 /* first, we will invert the proxy list order */
7418 curproxy = NULL;
7419 while (proxy) {
7420 struct proxy *next;
7421
7422 next = proxy->next;
7423 proxy->next = curproxy;
7424 curproxy = proxy;
7425 if (!next)
7426 break;
7427 proxy = next;
7428 }
7429
Willy Tarreau419ead82014-09-16 13:41:21 +02007430 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007431 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007432 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007433 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007434 struct act_rule *trule;
7435 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007436 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007437 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007438 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007439
Willy Tarreau050536d2012-10-04 08:47:34 +02007440 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007441 /* proxy ID not set, use automatic numbering with first
7442 * spare entry starting with next_pxid.
7443 */
7444 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7445 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7446 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007447 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007448 next_pxid++;
7449
Willy Tarreau55ea7572007-06-17 19:56:27 +02007450
Willy Tarreaubaaee002006-06-26 02:48:02 +02007451 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007452 /* ensure we don't keep listeners uselessly bound */
7453 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007454 free((void *)curproxy->table.peers.name);
7455 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007456 continue;
7457 }
7458
Willy Tarreau102df612014-05-07 23:56:38 +02007459 /* Check multi-process mode compatibility for the current proxy */
7460
7461 if (curproxy->bind_proc) {
7462 /* an explicit bind-process was specified, let's check how many
7463 * processes remain.
7464 */
David Carliere6c39412015-07-02 07:00:17 +00007465 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007466
7467 curproxy->bind_proc &= nbits(global.nbproc);
7468 if (!curproxy->bind_proc && nbproc == 1) {
7469 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);
7470 curproxy->bind_proc = 1;
7471 }
7472 else if (!curproxy->bind_proc && nbproc > 1) {
7473 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);
7474 curproxy->bind_proc = 0;
7475 }
7476 }
7477
Willy Tarreau3d209582014-05-09 17:06:11 +02007478 /* check and reduce the bind-proc of each listener */
7479 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7480 unsigned long mask;
7481
7482 if (!bind_conf->bind_proc)
7483 continue;
7484
7485 mask = nbits(global.nbproc);
7486 if (curproxy->bind_proc)
7487 mask &= curproxy->bind_proc;
7488 /* mask cannot be null here thanks to the previous checks */
7489
David Carliere6c39412015-07-02 07:00:17 +00007490 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007491 bind_conf->bind_proc &= mask;
7492
7493 if (!bind_conf->bind_proc && nbproc == 1) {
7494 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",
7495 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7496 bind_conf->bind_proc = mask & ~(mask - 1);
7497 }
7498 else if (!bind_conf->bind_proc && nbproc > 1) {
7499 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",
7500 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7501 bind_conf->bind_proc = 0;
7502 }
7503 }
7504
Willy Tarreauff01a212009-03-15 13:46:16 +01007505 switch (curproxy->mode) {
7506 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007507 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007508 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007509 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7510 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007511 cfgerr++;
7512 }
7513
7514 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007515 Warning("config : servers will be ignored for %s '%s'.\n",
7516 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007517 break;
7518
7519 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007520 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007521 break;
7522
7523 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007524 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 break;
7526 }
7527
Willy Tarreauf3934b82015-08-11 11:36:45 +02007528 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7529 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7530 proxy_type_str(curproxy), curproxy->id);
7531 err_code |= ERR_WARN;
7532 }
7533
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007534 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007535 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007536 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7538 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007539 cfgerr++;
7540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007541#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007542 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007543 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7544 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007545 cfgerr++;
7546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007547#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007548 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007549 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007551 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007552 }
7553 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007554 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007555 /* If no LB algo is set in a backend, and we're not in
7556 * transparent mode, dispatch mode nor proxy mode, we
7557 * want to use balance roundrobin by default.
7558 */
7559 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7560 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007561 }
7562 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007563
Willy Tarreau1620ec32011-08-06 17:05:02 +02007564 if (curproxy->options & PR_O_DISPATCH)
7565 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7566 else if (curproxy->options & PR_O_HTTP_PROXY)
7567 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7568 else if (curproxy->options & PR_O_TRANSP)
7569 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007570
Willy Tarreau1620ec32011-08-06 17:05:02 +02007571 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7572 if (curproxy->options & PR_O_DISABLE404) {
7573 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7574 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7575 err_code |= ERR_WARN;
7576 curproxy->options &= ~PR_O_DISABLE404;
7577 }
7578 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7579 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7580 "send-state", proxy_type_str(curproxy), curproxy->id);
7581 err_code |= ERR_WARN;
7582 curproxy->options &= ~PR_O2_CHK_SNDST;
7583 }
Willy Tarreauef781042010-01-27 11:53:01 +01007584 }
7585
Simon Horman98637e52014-06-20 12:30:16 +09007586 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7587 if (!global.external_check) {
7588 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7589 curproxy->id, "option external-check");
7590 cfgerr++;
7591 }
7592 if (!curproxy->check_command) {
7593 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7594 curproxy->id, "option external-check");
7595 cfgerr++;
7596 }
7597 }
7598
Simon Horman64e34162015-02-06 11:11:57 +09007599 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007600 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7601 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007602 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7603 "'email-alert myhostname', or 'email-alert to' "
7604 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007605 "to be present).\n",
7606 proxy_type_str(curproxy), curproxy->id);
7607 err_code |= ERR_WARN;
7608 free_email_alert(curproxy);
7609 }
7610 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007611 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007612 }
7613
Simon Horman98637e52014-06-20 12:30:16 +09007614 if (curproxy->check_command) {
7615 int clear = 0;
7616 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7617 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7618 "external-check command", proxy_type_str(curproxy), curproxy->id);
7619 err_code |= ERR_WARN;
7620 clear = 1;
7621 }
7622 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007623 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007624 curproxy->id, "external-check command");
7625 cfgerr++;
7626 }
7627 if (clear) {
7628 free(curproxy->check_command);
7629 curproxy->check_command = NULL;
7630 }
7631 }
7632
7633 if (curproxy->check_path) {
7634 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7635 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7636 "external-check path", proxy_type_str(curproxy), curproxy->id);
7637 err_code |= ERR_WARN;
7638 free(curproxy->check_path);
7639 curproxy->check_path = NULL;
7640 }
7641 }
7642
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007643 /* if a default backend was specified, let's find it */
7644 if (curproxy->defbe.name) {
7645 struct proxy *target;
7646
Willy Tarreauafb39922015-05-26 12:04:09 +02007647 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007648 if (!target) {
7649 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7650 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007651 cfgerr++;
7652 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007653 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7654 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007655 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007656 } else if (target->mode != curproxy->mode &&
7657 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7658
7659 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7660 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7661 curproxy->conf.file, curproxy->conf.line,
7662 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7663 target->conf.file, target->conf.line);
7664 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007665 } else {
7666 free(curproxy->defbe.name);
7667 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007668 /* Update tot_fe_maxconn for a further fullconn's computation */
7669 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007670 /* Emit a warning if this proxy also has some servers */
7671 if (curproxy->srv) {
7672 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7673 curproxy->id);
7674 err_code |= ERR_WARN;
7675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007676 }
7677 }
7678
Emeric Brun3f783572017-01-12 11:21:28 +01007679 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7680 /* Case of listen without default backend
7681 * The curproxy will be its own default backend
7682 * so we update tot_fe_maxconn for a further
7683 * fullconn's computation */
7684 curproxy->tot_fe_maxconn += curproxy->maxconn;
7685 }
7686
Willy Tarreau55ea7572007-06-17 19:56:27 +02007687 /* find the target proxy for 'use_backend' rules */
7688 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007689 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007690 struct logformat_node *node;
7691 char *pxname;
7692
7693 /* Try to parse the string as a log format expression. If the result
7694 * of the parsing is only one entry containing a simple string, then
7695 * it's a standard string corresponding to a static rule, thus the
7696 * parsing is cancelled and be.name is restored to be resolved.
7697 */
7698 pxname = rule->be.name;
7699 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007700 curproxy->conf.args.ctx = ARGC_UBK;
7701 curproxy->conf.args.file = rule->file;
7702 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007703 err = NULL;
7704 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7705 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7706 rule->file, rule->line, pxname, err);
7707 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007708 cfgerr++;
7709 continue;
7710 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007711 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7712
7713 if (!LIST_ISEMPTY(&rule->be.expr)) {
7714 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7715 rule->dynamic = 1;
7716 free(pxname);
7717 continue;
7718 }
7719 /* simple string: free the expression and fall back to static rule */
7720 free(node->arg);
7721 free(node);
7722 }
7723
7724 rule->dynamic = 0;
7725 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007726
Willy Tarreauafb39922015-05-26 12:04:09 +02007727 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007728 if (!target) {
7729 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7730 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007731 cfgerr++;
7732 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007733 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7734 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007735 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007736 } else if (target->mode != curproxy->mode &&
7737 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7738
7739 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7740 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7741 curproxy->conf.file, curproxy->conf.line,
7742 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7743 target->conf.file, target->conf.line);
7744 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007745 } else {
7746 free((void *)rule->be.name);
7747 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007748 /* For each target of switching rules, we update
7749 * their tot_fe_maxconn, except if a previous rule point
7750 * on the same backend or on the default backend */
7751 if (rule->be.backend != curproxy->defbe.be) {
7752 struct switching_rule *swrule;
7753
7754 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7755 if (rule == swrule) {
7756 target->tot_fe_maxconn += curproxy->maxconn;
7757 break;
7758 }
7759 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7760 /* there is multiple ref of this backend */
7761 break;
7762 }
7763 }
7764 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007765 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007766 }
7767
Willy Tarreau64ab6072014-09-16 12:17:36 +02007768 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007769 list_for_each_entry(srule, &curproxy->server_rules, list) {
7770 struct server *target = findserver(curproxy, srule->srv.name);
7771
7772 if (!target) {
7773 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7774 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7775 cfgerr++;
7776 continue;
7777 }
7778 free((void *)srule->srv.name);
7779 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007780 }
7781
Emeric Brunb982a3d2010-01-04 15:45:53 +01007782 /* find the target table for 'stick' rules */
7783 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7784 struct proxy *target;
7785
Emeric Brun1d33b292010-01-04 15:47:17 +01007786 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7787 if (mrule->flags & STK_IS_STORE)
7788 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7789
Emeric Brunb982a3d2010-01-04 15:45:53 +01007790 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007791 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007792 else
7793 target = curproxy;
7794
7795 if (!target) {
7796 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7797 curproxy->id, mrule->table.name);
7798 cfgerr++;
7799 }
7800 else if (target->table.size == 0) {
7801 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7802 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7803 cfgerr++;
7804 }
Willy Tarreau12785782012-04-27 21:37:17 +02007805 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7806 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007807 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7808 cfgerr++;
7809 }
7810 else {
7811 free((void *)mrule->table.name);
7812 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007813 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007814 }
7815 }
7816
7817 /* find the target table for 'store response' rules */
7818 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7819 struct proxy *target;
7820
Emeric Brun1d33b292010-01-04 15:47:17 +01007821 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7822
Emeric Brunb982a3d2010-01-04 15:45:53 +01007823 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007824 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007825 else
7826 target = curproxy;
7827
7828 if (!target) {
7829 Alert("Proxy '%s': unable to find store table '%s'.\n",
7830 curproxy->id, mrule->table.name);
7831 cfgerr++;
7832 }
7833 else if (target->table.size == 0) {
7834 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7835 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7836 cfgerr++;
7837 }
Willy Tarreau12785782012-04-27 21:37:17 +02007838 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7839 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7841 cfgerr++;
7842 }
7843 else {
7844 free((void *)mrule->table.name);
7845 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007846 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007847 }
7848 }
7849
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007850 /* find the target table for 'tcp-request' layer 4 rules */
7851 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7852 struct proxy *target;
7853
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007854 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007855 continue;
7856
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007857 if (trule->arg.trk_ctr.table.n)
7858 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007859 else
7860 target = curproxy;
7861
7862 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007863 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007864 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007865 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007866 cfgerr++;
7867 }
7868 else if (target->table.size == 0) {
7869 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007870 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007871 cfgerr++;
7872 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007873 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007874 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007875 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007876 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007877 cfgerr++;
7878 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007879 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007880 free(trule->arg.trk_ctr.table.n);
7881 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007882 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007883 * to pass a list of counters to track and allocate them right here using
7884 * stktable_alloc_data_type().
7885 */
7886 }
7887 }
7888
Willy Tarreau620408f2016-10-21 16:37:51 +02007889 /* find the target table for 'tcp-request' layer 5 rules */
7890 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7891 struct proxy *target;
7892
7893 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7894 continue;
7895
7896 if (trule->arg.trk_ctr.table.n)
7897 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7898 else
7899 target = curproxy;
7900
7901 if (!target) {
7902 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7903 curproxy->id, trule->arg.trk_ctr.table.n,
7904 tcp_trk_idx(trule->action));
7905 cfgerr++;
7906 }
7907 else if (target->table.size == 0) {
7908 Alert("Proxy '%s': table '%s' used but not configured.\n",
7909 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7910 cfgerr++;
7911 }
7912 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7913 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7914 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7915 tcp_trk_idx(trule->action));
7916 cfgerr++;
7917 }
7918 else {
7919 free(trule->arg.trk_ctr.table.n);
7920 trule->arg.trk_ctr.table.t = &target->table;
7921 /* Note: if we decide to enhance the track-sc syntax, we may be able
7922 * to pass a list of counters to track and allocate them right here using
7923 * stktable_alloc_data_type().
7924 */
7925 }
7926 }
7927
Willy Tarreaud1f96522010-08-03 19:34:32 +02007928 /* find the target table for 'tcp-request' layer 6 rules */
7929 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7930 struct proxy *target;
7931
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007932 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007933 continue;
7934
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007935 if (trule->arg.trk_ctr.table.n)
7936 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007937 else
7938 target = curproxy;
7939
7940 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007941 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007942 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007943 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007944 cfgerr++;
7945 }
7946 else if (target->table.size == 0) {
7947 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007948 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007949 cfgerr++;
7950 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007951 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007952 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007953 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007954 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007955 cfgerr++;
7956 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007957 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007958 free(trule->arg.trk_ctr.table.n);
7959 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007960 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007961 * to pass a list of counters to track and allocate them right here using
7962 * stktable_alloc_data_type().
7963 */
7964 }
7965 }
7966
Baptiste Assmanne9544932015-11-03 23:31:35 +01007967 /* parse http-request capture rules to ensure id really exists */
7968 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7969 if (hrqrule->action != ACT_CUSTOM ||
7970 hrqrule->action_ptr != http_action_req_capture_by_id)
7971 continue;
7972
7973 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7974 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7975 curproxy->id, hrqrule->arg.capid.idx);
7976 cfgerr++;
7977 }
7978 }
7979
7980 /* parse http-response capture rules to ensure id really exists */
7981 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7982 if (hrqrule->action != ACT_CUSTOM ||
7983 hrqrule->action_ptr != http_action_res_capture_by_id)
7984 continue;
7985
7986 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7987 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7988 curproxy->id, hrqrule->arg.capid.idx);
7989 cfgerr++;
7990 }
7991 }
7992
Willy Tarreau09448f72014-06-25 18:12:15 +02007993 /* find the target table for 'http-request' layer 7 rules */
7994 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7995 struct proxy *target;
7996
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007997 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007998 continue;
7999
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008000 if (hrqrule->arg.trk_ctr.table.n)
8001 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008002 else
8003 target = curproxy;
8004
8005 if (!target) {
8006 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008007 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008008 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008009 cfgerr++;
8010 }
8011 else if (target->table.size == 0) {
8012 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008013 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008014 cfgerr++;
8015 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008016 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008017 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008018 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008019 http_trk_idx(hrqrule->action));
8020 cfgerr++;
8021 }
8022 else {
8023 free(hrqrule->arg.trk_ctr.table.n);
8024 hrqrule->arg.trk_ctr.table.t = &target->table;
8025 /* Note: if we decide to enhance the track-sc syntax, we may be able
8026 * to pass a list of counters to track and allocate them right here using
8027 * stktable_alloc_data_type().
8028 */
8029 }
8030 }
8031
8032 /* find the target table for 'http-response' layer 7 rules */
8033 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8034 struct proxy *target;
8035
8036 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8037 continue;
8038
8039 if (hrqrule->arg.trk_ctr.table.n)
8040 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8041 else
8042 target = curproxy;
8043
8044 if (!target) {
8045 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8046 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8047 http_trk_idx(hrqrule->action));
8048 cfgerr++;
8049 }
8050 else if (target->table.size == 0) {
8051 Alert("Proxy '%s': table '%s' used but not configured.\n",
8052 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8053 cfgerr++;
8054 }
8055 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8056 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8057 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8058 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008059 cfgerr++;
8060 }
8061 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008062 free(hrqrule->arg.trk_ctr.table.n);
8063 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008064 /* Note: if we decide to enhance the track-sc syntax, we may be able
8065 * to pass a list of counters to track and allocate them right here using
8066 * stktable_alloc_data_type().
8067 */
8068 }
8069 }
8070
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008071 /* move any "block" rules at the beginning of the http-request rules */
8072 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8073 /* insert block_rules into http_req_rules at the beginning */
8074 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8075 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8076 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8077 curproxy->http_req_rules.n = curproxy->block_rules.n;
8078 LIST_INIT(&curproxy->block_rules);
8079 }
8080
Emeric Brun32da3c42010-09-23 18:39:19 +02008081 if (curproxy->table.peers.name) {
8082 struct peers *curpeers = peers;
8083
8084 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8085 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8086 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008087 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008088 break;
8089 }
8090 }
8091
8092 if (!curpeers) {
8093 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8094 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008095 free((void *)curproxy->table.peers.name);
8096 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008097 cfgerr++;
8098 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008099 else if (curpeers->state == PR_STSTOPPED) {
8100 /* silently disable this peers section */
8101 curproxy->table.peers.p = NULL;
8102 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008103 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008104 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8105 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008106 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008107 cfgerr++;
8108 }
8109 }
8110
Simon Horman9dc49962015-01-30 11:22:59 +09008111
8112 if (curproxy->email_alert.mailers.name) {
8113 struct mailers *curmailers = mailers;
8114
8115 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8116 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8117 free(curproxy->email_alert.mailers.name);
8118 curproxy->email_alert.mailers.m = curmailers;
8119 curmailers->users++;
8120 break;
8121 }
8122 }
8123
8124 if (!curmailers) {
8125 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8126 curproxy->id, curproxy->email_alert.mailers.name);
8127 free_email_alert(curproxy);
8128 cfgerr++;
8129 }
8130 }
8131
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008132 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008133 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008134 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8135 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8136 "proxy", curproxy->id);
8137 cfgerr++;
8138 goto out_uri_auth_compat;
8139 }
8140
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008141 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008142 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008143 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008144 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008145
Willy Tarreau95fa4692010-02-01 13:05:50 +01008146 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8147 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008148
8149 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008150 uri_auth_compat_req[i++] = "realm";
8151 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8152 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008153
Willy Tarreau95fa4692010-02-01 13:05:50 +01008154 uri_auth_compat_req[i++] = "unless";
8155 uri_auth_compat_req[i++] = "{";
8156 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8157 uri_auth_compat_req[i++] = "}";
8158 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008159
Willy Tarreauff011f22011-01-06 17:51:27 +01008160 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8161 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008162 cfgerr++;
8163 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008164 }
8165
Willy Tarreauff011f22011-01-06 17:51:27 +01008166 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008167
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008168 if (curproxy->uri_auth->auth_realm) {
8169 free(curproxy->uri_auth->auth_realm);
8170 curproxy->uri_auth->auth_realm = NULL;
8171 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008172
8173 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008174 }
8175out_uri_auth_compat:
8176
Dragan Dosen43885c72015-10-01 13:18:13 +02008177 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008178 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008179 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8180 if (!curproxy->conf.logformat_sd_string) {
8181 /* set the default logformat_sd_string */
8182 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8183 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008184 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008185 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008186 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008187
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008188 /* compile the log format */
8189 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008190 if (curproxy->conf.logformat_string != default_http_log_format &&
8191 curproxy->conf.logformat_string != default_tcp_log_format &&
8192 curproxy->conf.logformat_string != clf_http_log_format)
8193 free(curproxy->conf.logformat_string);
8194 curproxy->conf.logformat_string = NULL;
8195 free(curproxy->conf.lfs_file);
8196 curproxy->conf.lfs_file = NULL;
8197 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008198
8199 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8200 free(curproxy->conf.logformat_sd_string);
8201 curproxy->conf.logformat_sd_string = NULL;
8202 free(curproxy->conf.lfsd_file);
8203 curproxy->conf.lfsd_file = NULL;
8204 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008205 }
8206
Willy Tarreau62a61232013-04-12 18:13:46 +02008207 if (curproxy->conf.logformat_string) {
8208 curproxy->conf.args.ctx = ARGC_LOG;
8209 curproxy->conf.args.file = curproxy->conf.lfs_file;
8210 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008211 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008212 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008213 SMP_VAL_FE_LOG_END, &err)) {
8214 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8215 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8216 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008217 cfgerr++;
8218 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008219 curproxy->conf.args.file = NULL;
8220 curproxy->conf.args.line = 0;
8221 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008222
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008223 if (curproxy->conf.logformat_sd_string) {
8224 curproxy->conf.args.ctx = ARGC_LOGSD;
8225 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8226 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008227 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008228 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008229 SMP_VAL_FE_LOG_END, &err)) {
8230 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8231 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8232 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008233 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008234 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8235 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8236 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8237 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008238 cfgerr++;
8239 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008240 curproxy->conf.args.file = NULL;
8241 curproxy->conf.args.line = 0;
8242 }
8243
Willy Tarreau62a61232013-04-12 18:13:46 +02008244 if (curproxy->conf.uniqueid_format_string) {
8245 curproxy->conf.args.ctx = ARGC_UIF;
8246 curproxy->conf.args.file = curproxy->conf.uif_file;
8247 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008248 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008249 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008250 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8251 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8252 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8253 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008254 cfgerr++;
8255 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008256 curproxy->conf.args.file = NULL;
8257 curproxy->conf.args.line = 0;
8258 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008259
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008260 /* only now we can check if some args remain unresolved.
8261 * This must be done after the users and groups resolution.
8262 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008263 cfgerr += smp_resolve_args(curproxy);
8264 if (!cfgerr)
8265 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008266
Willy Tarreau2738a142006-07-08 17:28:09 +02008267 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008268 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008269 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008270 (!curproxy->timeout.connect ||
8271 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008272 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008273 " | While not properly invalid, you will certainly encounter various problems\n"
8274 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008275 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008276 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008277 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008278 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008279
Willy Tarreau1fa31262007-12-03 00:36:16 +01008280 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8281 * We must still support older configurations, so let's find out whether those
8282 * parameters have been set or must be copied from contimeouts.
8283 */
8284 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008285 if (!curproxy->timeout.tarpit ||
8286 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008287 /* tarpit timeout not set. We search in the following order:
8288 * default.tarpit, curr.connect, default.connect.
8289 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008290 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008291 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008292 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008293 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008294 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008295 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008296 }
8297 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008298 (!curproxy->timeout.queue ||
8299 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008300 /* queue timeout not set. We search in the following order:
8301 * default.queue, curr.connect, default.connect.
8302 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008303 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008304 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008305 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008306 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008307 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008308 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008309 }
8310 }
8311
Willy Tarreau1620ec32011-08-06 17:05:02 +02008312 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008313 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008314 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008315 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008316 }
8317
Willy Tarreau215663d2014-06-13 18:30:23 +02008318 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8319 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8320 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8321 proxy_type_str(curproxy), curproxy->id);
8322 err_code |= ERR_WARN;
8323 }
8324
Willy Tarreau193b8c62012-11-22 00:17:38 +01008325 /* ensure that cookie capture length is not too large */
8326 if (curproxy->capture_len >= global.tune.cookie_len) {
8327 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8328 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8329 err_code |= ERR_WARN;
8330 curproxy->capture_len = global.tune.cookie_len - 1;
8331 }
8332
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008333 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008334 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008335 curproxy->req_cap_pool = create_pool("ptrcap",
8336 curproxy->nb_req_cap * sizeof(char *),
8337 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008338 }
8339
8340 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008341 curproxy->rsp_cap_pool = create_pool("ptrcap",
8342 curproxy->nb_rsp_cap * sizeof(char *),
8343 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008344 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008345
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008346 switch (curproxy->load_server_state_from_file) {
8347 case PR_SRV_STATE_FILE_UNSPEC:
8348 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8349 break;
8350 case PR_SRV_STATE_FILE_GLOBAL:
8351 if (!global.server_state_file) {
8352 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",
8353 curproxy->id);
8354 err_code |= ERR_WARN;
8355 }
8356 break;
8357 }
8358
Willy Tarreaubaaee002006-06-26 02:48:02 +02008359 /* first, we will invert the servers list order */
8360 newsrv = NULL;
8361 while (curproxy->srv) {
8362 struct server *next;
8363
8364 next = curproxy->srv->next;
8365 curproxy->srv->next = newsrv;
8366 newsrv = curproxy->srv;
8367 if (!next)
8368 break;
8369 curproxy->srv = next;
8370 }
8371
Willy Tarreau17edc812014-01-03 12:14:34 +01008372 /* Check that no server name conflicts. This causes trouble in the stats.
8373 * We only emit a warning for the first conflict affecting each server,
8374 * in order to avoid combinatory explosion if all servers have the same
8375 * name. We do that only for servers which do not have an explicit ID,
8376 * because these IDs were made also for distinguishing them and we don't
8377 * want to annoy people who correctly manage them.
8378 */
8379 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8380 struct server *other_srv;
8381
8382 if (newsrv->puid)
8383 continue;
8384
8385 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8386 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8387 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8388 newsrv->conf.file, newsrv->conf.line,
8389 proxy_type_str(curproxy), curproxy->id,
8390 newsrv->id, other_srv->conf.line);
8391 break;
8392 }
8393 }
8394 }
8395
Willy Tarreaudd701652010-05-25 23:03:02 +02008396 /* assign automatic UIDs to servers which don't have one yet */
8397 next_id = 1;
8398 newsrv = curproxy->srv;
8399 while (newsrv != NULL) {
8400 if (!newsrv->puid) {
8401 /* server ID not set, use automatic numbering with first
8402 * spare entry starting with next_svid.
8403 */
8404 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8405 newsrv->conf.id.key = newsrv->puid = next_id;
8406 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8407 }
8408 next_id++;
8409 newsrv = newsrv->next;
8410 }
8411
Willy Tarreau20697042007-11-15 23:26:18 +01008412 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008413 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008414
Willy Tarreau62c3be22012-01-20 13:12:32 +01008415 /*
8416 * If this server supports a maxconn parameter, it needs a dedicated
8417 * tasks to fill the emptied slots when a connection leaves.
8418 * Also, resolve deferred tracking dependency if needed.
8419 */
8420 newsrv = curproxy->srv;
8421 while (newsrv != NULL) {
8422 if (newsrv->minconn > newsrv->maxconn) {
8423 /* Only 'minconn' was specified, or it was higher than or equal
8424 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8425 * this will avoid further useless expensive computations.
8426 */
8427 newsrv->maxconn = newsrv->minconn;
8428 } else if (newsrv->maxconn && !newsrv->minconn) {
8429 /* minconn was not specified, so we set it to maxconn */
8430 newsrv->minconn = newsrv->maxconn;
8431 }
8432
Willy Tarreau17d45382016-12-22 21:16:08 +01008433 /* this will also properly set the transport layer for prod and checks */
8434 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8435 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8436 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8437 }
Emeric Brun94324a42012-10-11 14:00:19 +02008438
Willy Tarreau2f075e92013-12-03 11:11:34 +01008439 /* set the check type on the server */
8440 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8441
Willy Tarreau62c3be22012-01-20 13:12:32 +01008442 if (newsrv->trackit) {
8443 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008444 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008445 char *pname, *sname;
8446
8447 pname = newsrv->trackit;
8448 sname = strrchr(pname, '/');
8449
8450 if (sname)
8451 *sname++ = '\0';
8452 else {
8453 sname = pname;
8454 pname = NULL;
8455 }
8456
8457 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008458 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008459 if (!px) {
8460 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8461 proxy_type_str(curproxy), curproxy->id,
8462 newsrv->id, pname);
8463 cfgerr++;
8464 goto next_srv;
8465 }
8466 } else
8467 px = curproxy;
8468
8469 srv = findserver(px, sname);
8470 if (!srv) {
8471 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8472 proxy_type_str(curproxy), curproxy->id,
8473 newsrv->id, sname);
8474 cfgerr++;
8475 goto next_srv;
8476 }
8477
Willy Tarreau32091232014-05-16 13:52:00 +02008478 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8479 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8480 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008481 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008482 "tracking as it does not have any check nor agent enabled.\n",
8483 proxy_type_str(curproxy), curproxy->id,
8484 newsrv->id, px->id, srv->id);
8485 cfgerr++;
8486 goto next_srv;
8487 }
8488
8489 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8490
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008491 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008492 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8493 "belongs to a tracking chain looping back to %s/%s.\n",
8494 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008495 newsrv->id, px->id, srv->id, px->id,
8496 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008497 cfgerr++;
8498 goto next_srv;
8499 }
8500
8501 if (curproxy != px &&
8502 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8503 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8504 "tracking: disable-on-404 option inconsistency.\n",
8505 proxy_type_str(curproxy), curproxy->id,
8506 newsrv->id, px->id, srv->id);
8507 cfgerr++;
8508 goto next_srv;
8509 }
8510
Willy Tarreau62c3be22012-01-20 13:12:32 +01008511 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008512 newsrv->tracknext = srv->trackers;
8513 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514
8515 free(newsrv->trackit);
8516 newsrv->trackit = NULL;
8517 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008518
8519 /*
8520 * resolve server's resolvers name and update the resolvers pointer
8521 * accordingly
8522 */
8523 if (newsrv->resolvers_id) {
8524 struct dns_resolvers *curr_resolvers;
8525 int found;
8526
8527 found = 0;
8528 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8529 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8530 found = 1;
8531 break;
8532 }
8533 }
8534
8535 if (!found) {
8536 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8537 proxy_type_str(curproxy), curproxy->id,
8538 newsrv->id, newsrv->resolvers_id);
8539 cfgerr++;
8540 } else {
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008541 if (newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008542 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008543 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8544 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8545 proxy_type_str(curproxy), curproxy->id,
8546 newsrv->id);
8547 cfgerr++;
8548 }
8549 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008550 }
8551 }
8552 else {
8553 /* if no resolvers section associated to this server
8554 * we can clean up the associated resolution structure
8555 */
8556 if (newsrv->resolution) {
8557 free(newsrv->resolution->hostname_dn);
8558 newsrv->resolution->hostname_dn = NULL;
8559 free(newsrv->resolution);
8560 newsrv->resolution = NULL;
8561 }
8562 }
8563
Willy Tarreau62c3be22012-01-20 13:12:32 +01008564 next_srv:
8565 newsrv = newsrv->next;
8566 }
8567
Olivier Houchard4e694042017-03-14 20:01:29 +01008568 /*
8569 * Try to generate dynamic cookies for servers now.
8570 * It couldn't be done earlier, since at the time we parsed
8571 * the server line, we may not have known yet that we
8572 * should use dynamic cookies, or the secret key may not
8573 * have been provided yet.
8574 */
8575 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8576 newsrv = curproxy->srv;
8577 while (newsrv != NULL) {
8578 srv_set_dyncookie(newsrv);
8579 newsrv = newsrv->next;
8580 }
8581
8582 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008583 /* We have to initialize the server lookup mechanism depending
8584 * on what LB algorithm was choosen.
8585 */
8586
8587 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8588 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8589 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008590 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8591 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8592 init_server_map(curproxy);
8593 } else {
8594 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8595 fwrr_init_server_groups(curproxy);
8596 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008597 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008598
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008599 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008600 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8601 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8602 fwlc_init_server_tree(curproxy);
8603 } else {
8604 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8605 fas_init_server_tree(curproxy);
8606 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008607 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008608
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008609 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008610 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8611 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8612 chash_init_server_tree(curproxy);
8613 } else {
8614 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8615 init_server_map(curproxy);
8616 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008617 break;
8618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008619
8620 if (curproxy->options & PR_O_LOGASAP)
8621 curproxy->to_log &= ~LW_BYTES;
8622
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008623 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008624 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8625 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008626 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8627 proxy_type_str(curproxy), curproxy->id);
8628 err_code |= ERR_WARN;
8629 }
8630
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008631 if (curproxy->mode != PR_MODE_HTTP) {
8632 int optnum;
8633
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008634 if (curproxy->uri_auth) {
8635 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8636 proxy_type_str(curproxy), curproxy->id);
8637 err_code |= ERR_WARN;
8638 curproxy->uri_auth = NULL;
8639 }
8640
Willy Tarreaude7dc882017-03-10 11:49:21 +01008641 if (curproxy->capture_name) {
8642 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8643 proxy_type_str(curproxy), curproxy->id);
8644 err_code |= ERR_WARN;
8645 }
8646
8647 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8648 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8649 proxy_type_str(curproxy), curproxy->id);
8650 err_code |= ERR_WARN;
8651 }
8652
8653 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8654 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8655 proxy_type_str(curproxy), curproxy->id);
8656 err_code |= ERR_WARN;
8657 }
8658
8659 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8660 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8661 proxy_type_str(curproxy), curproxy->id);
8662 err_code |= ERR_WARN;
8663 }
8664
8665 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8666 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8667 proxy_type_str(curproxy), curproxy->id);
8668 err_code |= ERR_WARN;
8669 }
8670
Willy Tarreau87cf5142011-08-19 22:57:24 +02008671 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008672 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8673 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8674 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008675 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008676 }
8677
8678 if (curproxy->options & PR_O_ORGTO) {
8679 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8680 "originalto", proxy_type_str(curproxy), curproxy->id);
8681 err_code |= ERR_WARN;
8682 curproxy->options &= ~PR_O_ORGTO;
8683 }
8684
8685 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8686 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8687 (curproxy->cap & cfg_opts[optnum].cap) &&
8688 (curproxy->options & cfg_opts[optnum].val)) {
8689 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8690 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8691 err_code |= ERR_WARN;
8692 curproxy->options &= ~cfg_opts[optnum].val;
8693 }
8694 }
8695
8696 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8697 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8698 (curproxy->cap & cfg_opts2[optnum].cap) &&
8699 (curproxy->options2 & cfg_opts2[optnum].val)) {
8700 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8701 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8702 err_code |= ERR_WARN;
8703 curproxy->options2 &= ~cfg_opts2[optnum].val;
8704 }
8705 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008706
Willy Tarreau29fbe512015-08-20 19:35:14 +02008707#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008708 if (curproxy->conn_src.bind_hdr_occ) {
8709 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008710 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008711 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008712 err_code |= ERR_WARN;
8713 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008714#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008715 }
8716
Willy Tarreaubaaee002006-06-26 02:48:02 +02008717 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008718 * ensure that we're not cross-dressing a TCP server into HTTP.
8719 */
8720 newsrv = curproxy->srv;
8721 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008722 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008723 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8724 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008725 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008726 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008727
Willy Tarreau0cec3312011-10-31 13:49:26 +01008728 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8729 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8730 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8731 err_code |= ERR_WARN;
8732 }
8733
Willy Tarreauc93cd162014-05-13 15:54:22 +02008734 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008735 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8736 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8737 err_code |= ERR_WARN;
8738 }
8739
Willy Tarreau29fbe512015-08-20 19:35:14 +02008740#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008741 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8742 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008743 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 +01008744 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008745 err_code |= ERR_WARN;
8746 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008747#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008748
8749 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8750 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8751 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8752 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8753 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8754 Warning("config : %s '%s' : connections to server '%s' use the client's IP address as the source while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'usesrc' and to use the 'forwardfor' option instead.\n",
8755 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8756 err_code |= ERR_WARN;
8757 }
8758
8759
8760 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8761 Warning("config : %s '%s' : connections to server '%s' will have a PROXY protocol header announcing the first client's IP address while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'send-proxy' and to use the 'forwardfor' option instead.\n",
8762 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8763 err_code |= ERR_WARN;
8764 }
8765 }
8766
Willy Tarreau21d2af32008-02-14 20:25:24 +01008767 newsrv = newsrv->next;
8768 }
8769
Willy Tarreaue42bd962014-09-16 16:21:19 +02008770 /* check if we have a frontend with "tcp-request content" looking at L7
8771 * with no inspect-delay
8772 */
8773 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8774 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008775 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008776 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008777 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008778 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008779 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008780 break;
8781 }
8782
8783 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8784 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8785 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8786 " This means that these rules will randomly find their contents. This can be fixed by"
8787 " setting the tcp-request inspect-delay.\n",
8788 proxy_type_str(curproxy), curproxy->id);
8789 err_code |= ERR_WARN;
8790 }
8791 }
8792
Christopher Fauletd7c91962015-04-30 11:48:27 +02008793 /* Check filter configuration, if any */
8794 cfgerr += flt_check(curproxy);
8795
Willy Tarreauc1a21672009-08-16 22:37:44 +02008796 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008797 if (!curproxy->accept)
8798 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008799
Willy Tarreauc1a21672009-08-16 22:37:44 +02008800 if (curproxy->tcp_req.inspect_delay ||
8801 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008802 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008803
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008804 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008805 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008806 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008807 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008808
8809 /* both TCP and HTTP must check switching rules */
8810 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008811
8812 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008813 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008814 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8815 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008816 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008817 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8818 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008819 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008820 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008821 }
8822
8823 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008824 if (curproxy->tcp_req.inspect_delay ||
8825 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8826 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8827
Emeric Brun97679e72010-09-23 17:56:44 +02008828 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8829 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8830
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008831 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008832 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008833 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008834 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008835
8836 /* If the backend does requires RDP cookie persistence, we have to
8837 * enable the corresponding analyser.
8838 */
8839 if (curproxy->options2 & PR_O2_RDPC_PRST)
8840 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008841
8842 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008843 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008844 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8845 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008846 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008847 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8848 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008849 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008850 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008851 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008852 }
8853
8854 /***********************************************************/
8855 /* At this point, target names have already been resolved. */
8856 /***********************************************************/
8857
8858 /* Check multi-process mode compatibility */
8859
8860 if (global.nbproc > 1 && global.stats_fe) {
8861 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8862 unsigned long mask;
8863
8864 mask = nbits(global.nbproc);
8865 if (global.stats_fe->bind_proc)
8866 mask &= global.stats_fe->bind_proc;
8867
8868 if (bind_conf->bind_proc)
8869 mask &= bind_conf->bind_proc;
8870
8871 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008872 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008873 break;
8874 }
8875 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8876 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");
8877 }
8878 }
8879
8880 /* Make each frontend inherit bind-process from its listeners when not specified. */
8881 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8882 if (curproxy->bind_proc)
8883 continue;
8884
8885 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8886 unsigned long mask;
8887
Willy Tarreaue428b082015-05-04 21:57:58 +02008888 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008889 curproxy->bind_proc |= mask;
8890 }
8891
8892 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008893 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008894 }
8895
8896 if (global.stats_fe) {
8897 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8898 unsigned long mask;
8899
Cyril Bonté06181952016-02-24 00:14:54 +01008900 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008901 global.stats_fe->bind_proc |= mask;
8902 }
8903 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008904 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008905 }
8906
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008907 /* propagate bindings from frontends to backends. Don't do it if there
8908 * are any fatal errors as we must not call it with unresolved proxies.
8909 */
8910 if (!cfgerr) {
8911 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8912 if (curproxy->cap & PR_CAP_FE)
8913 propagate_processes(curproxy, NULL);
8914 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008915 }
8916
8917 /* Bind each unbound backend to all processes when not specified. */
8918 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8919 if (curproxy->bind_proc)
8920 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008921 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008922 }
8923
8924 /*******************************************************/
8925 /* At this step, all proxies have a non-null bind_proc */
8926 /*******************************************************/
8927
8928 /* perform the final checks before creating tasks */
8929
8930 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8931 struct listener *listener;
8932 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008933
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008934 /* Configure SSL for each bind line.
8935 * Note: if configuration fails at some point, the ->ctx member
8936 * remains NULL so that listeners can later detach.
8937 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008938 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008939 if (bind_conf->xprt->prepare_bind_conf &&
8940 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008941 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008942 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008943
Willy Tarreaue6b98942007-10-29 01:09:36 +01008944 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008945 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008946 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008947 int nbproc;
8948
8949 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008950 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008951 nbits(global.nbproc));
8952
8953 if (!nbproc) /* no intersection between listener and frontend */
8954 nbproc = 1;
8955
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008956 if (!listener->luid) {
8957 /* listener ID not set, use automatic numbering with first
8958 * spare entry starting with next_luid.
8959 */
8960 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8961 listener->conf.id.key = listener->luid = next_id;
8962 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008963 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008964 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008965
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008966 /* enable separate counters */
8967 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008968 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008969 if (!listener->name)
8970 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008971 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008972
Willy Tarreaue6b98942007-10-29 01:09:36 +01008973 if (curproxy->options & PR_O_TCP_NOLING)
8974 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008975 if (!listener->maxconn)
8976 listener->maxconn = curproxy->maxconn;
8977 if (!listener->backlog)
8978 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008979 if (!listener->maxaccept)
8980 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8981
8982 /* we want to have an optimal behaviour on single process mode to
8983 * maximize the work at once, but in multi-process we want to keep
8984 * some fairness between processes, so we target half of the max
8985 * number of events to be balanced over all the processes the proxy
8986 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8987 * used to disable the limit.
8988 */
8989 if (listener->maxaccept > 0) {
8990 if (nbproc > 1)
8991 listener->maxaccept = (listener->maxaccept + 1) / 2;
8992 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8993 }
8994
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008995 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008996 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008997 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008998 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008999
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009000 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009001 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009002
Willy Tarreau620408f2016-10-21 16:37:51 +02009003 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9004 listener->options |= LI_O_TCP_L5_RULES;
9005
Willy Tarreaude3041d2010-05-31 10:56:17 +02009006 if (curproxy->mon_mask.s_addr)
9007 listener->options |= LI_O_CHK_MONNET;
9008
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009009 /* smart accept mode is automatic in HTTP mode */
9010 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009011 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009012 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9013 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009014 }
9015
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009016 /* Release unused SSL configs */
9017 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009018 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9019 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009020 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009021
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009022 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009023 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009024 int count, maxproc = 0;
9025
9026 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009027 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009028 if (count > maxproc)
9029 maxproc = count;
9030 }
9031 /* backends have 0, frontends have 1 or more */
9032 if (maxproc != 1)
9033 Warning("Proxy '%s': in multi-process mode, stats will be"
9034 " limited to process assigned to the current request.\n",
9035 curproxy->id);
9036
Willy Tarreau102df612014-05-07 23:56:38 +02009037 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9038 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9039 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009040 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009041 }
Willy Tarreau102df612014-05-07 23:56:38 +02009042 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9043 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9044 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009045 }
9046 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009047
9048 /* create the task associated with the proxy */
9049 curproxy->task = task_new();
9050 if (curproxy->task) {
9051 curproxy->task->context = curproxy;
9052 curproxy->task->process = manage_proxy;
9053 /* no need to queue, it will be done automatically if some
9054 * listener gets limited.
9055 */
9056 curproxy->task->expire = TICK_ETERNITY;
9057 } else {
9058 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9059 curproxy->id);
9060 cfgerr++;
9061 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009062 }
9063
Willy Tarreaufbb78422011-06-05 15:38:35 +02009064 /* automatically compute fullconn if not set. We must not do it in the
9065 * loop above because cross-references are not yet fully resolved.
9066 */
9067 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9068 /* If <fullconn> is not set, let's set it to 10% of the sum of
9069 * the possible incoming frontend's maxconns.
9070 */
9071 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009072 /* we have the sum of the maxconns in <total>. We only
9073 * keep 10% of that sum to set the default fullconn, with
9074 * a hard minimum of 1 (to avoid a divide by zero).
9075 */
Emeric Brun3f783572017-01-12 11:21:28 +01009076 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009077 if (!curproxy->fullconn)
9078 curproxy->fullconn = 1;
9079 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009080 }
9081
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009082 /*
9083 * Recount currently required checks.
9084 */
9085
9086 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9087 int optnum;
9088
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009089 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9090 if (curproxy->options & cfg_opts[optnum].val)
9091 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009092
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009093 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9094 if (curproxy->options2 & cfg_opts2[optnum].val)
9095 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009096 }
9097
Willy Tarreau0fca4832015-05-01 19:12:05 +02009098 /* compute the required process bindings for the peers */
9099 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9100 if (curproxy->table.peers.p)
9101 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9102
Willy Tarreau122541c2011-09-07 21:24:49 +02009103 if (peers) {
9104 struct peers *curpeers = peers, **last;
9105 struct peer *p, *pb;
9106
Willy Tarreau1e273012015-05-01 19:15:17 +02009107 /* Remove all peers sections which don't have a valid listener,
9108 * which are not used by any table, or which are bound to more
9109 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009110 */
9111 last = &peers;
9112 while (*last) {
9113 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009114
9115 if (curpeers->state == PR_STSTOPPED) {
9116 /* the "disabled" keyword was present */
9117 if (curpeers->peers_fe)
9118 stop_proxy(curpeers->peers_fe);
9119 curpeers->peers_fe = NULL;
9120 }
9121 else if (!curpeers->peers_fe) {
9122 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9123 curpeers->id, localpeer);
9124 }
David Carliere6c39412015-07-02 07:00:17 +00009125 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009126 /* either it's totally stopped or too much used */
9127 if (curpeers->peers_fe->bind_proc) {
9128 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009129 "running in different processes (%d different ones). "
9130 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009131 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009132 cfgerr++;
9133 }
9134 stop_proxy(curpeers->peers_fe);
9135 curpeers->peers_fe = NULL;
9136 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009137 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009138 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009139 last = &curpeers->next;
9140 continue;
9141 }
9142
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009143 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009144 p = curpeers->remote;
9145 while (p) {
9146 pb = p->next;
9147 free(p->id);
9148 free(p);
9149 p = pb;
9150 }
9151
9152 /* Destroy and unlink this curpeers section.
9153 * Note: curpeers is backed up into *last.
9154 */
9155 free(curpeers->id);
9156 curpeers = curpeers->next;
9157 free(*last);
9158 *last = curpeers;
9159 }
9160 }
9161
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009162 /* initialize stick-tables on backend capable proxies. This must not
9163 * be done earlier because the data size may be discovered while parsing
9164 * other proxies.
9165 */
9166 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9167 if (curproxy->state == PR_STSTOPPED)
9168 continue;
9169
9170 if (!stktable_init(&curproxy->table)) {
9171 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9172 cfgerr++;
9173 }
9174 }
9175
Simon Horman0d16a402015-01-30 11:22:58 +09009176 if (mailers) {
9177 struct mailers *curmailers = mailers, **last;
9178 struct mailer *m, *mb;
9179
9180 /* Remove all mailers sections which don't have a valid listener.
9181 * This can happen when a mailers section is never referenced.
9182 */
9183 last = &mailers;
9184 while (*last) {
9185 curmailers = *last;
9186 if (curmailers->users) {
9187 last = &curmailers->next;
9188 continue;
9189 }
9190
9191 Warning("Removing incomplete section 'mailers %s'.\n",
9192 curmailers->id);
9193
9194 m = curmailers->mailer_list;
9195 while (m) {
9196 mb = m->next;
9197 free(m->id);
9198 free(m);
9199 m = mb;
9200 }
9201
9202 /* Destroy and unlink this curmailers section.
9203 * Note: curmailers is backed up into *last.
9204 */
9205 free(curmailers->id);
9206 curmailers = curmailers->next;
9207 free(*last);
9208 *last = curmailers;
9209 }
9210 }
9211
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009212 /* Update server_state_file_name to backend name if backend is supposed to use
9213 * a server-state file locally defined and none has been provided */
9214 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9215 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9216 curproxy->server_state_file_name == NULL)
9217 curproxy->server_state_file_name = strdup(curproxy->id);
9218 }
9219
Willy Tarreau34eb6712011-10-24 18:15:04 +02009220 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009221 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009222 MEM_F_SHARED);
9223
Willy Tarreaubb925012009-07-23 13:36:36 +02009224 if (cfgerr > 0)
9225 err_code |= ERR_ALERT | ERR_FATAL;
9226 out:
9227 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009228}
9229
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009230/*
9231 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9232 * parsing sessions.
9233 */
9234void cfg_register_keywords(struct cfg_kw_list *kwl)
9235{
9236 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9237}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009238
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009239/*
9240 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9241 */
9242void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9243{
9244 LIST_DEL(&kwl->list);
9245 LIST_INIT(&kwl->list);
9246}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009247
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009248/* this function register new section in the haproxy configuration file.
9249 * <section_name> is the name of this new section and <section_parser>
9250 * is the called parser. If two section declaration have the same name,
9251 * only the first declared is used.
9252 */
9253int cfg_register_section(char *section_name,
9254 int (*section_parser)(const char *, int, char **, int))
9255{
9256 struct cfg_section *cs;
9257
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009258 list_for_each_entry(cs, &sections, list) {
9259 if (strcmp(cs->section_name, section_name) == 0) {
9260 Alert("register section '%s': already registered.\n", section_name);
9261 return 0;
9262 }
9263 }
9264
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009265 cs = calloc(1, sizeof(*cs));
9266 if (!cs) {
9267 Alert("register section '%s': out of memory.\n", section_name);
9268 return 0;
9269 }
9270
9271 cs->section_name = section_name;
9272 cs->section_parser = section_parser;
9273
9274 LIST_ADDQ(&sections, &cs->list);
9275
9276 return 1;
9277}
9278
Willy Tarreaubaaee002006-06-26 02:48:02 +02009279/*
David Carlier845efb52015-09-25 11:49:18 +01009280 * free all config section entries
9281 */
9282void cfg_unregister_sections(void)
9283{
9284 struct cfg_section *cs, *ics;
9285
9286 list_for_each_entry_safe(cs, ics, &sections, list) {
9287 LIST_DEL(&cs->list);
9288 free(cs);
9289 }
9290}
9291
Christopher Faulet7110b402016-10-26 11:09:44 +02009292void cfg_backup_sections(struct list *backup_sections)
9293{
9294 struct cfg_section *cs, *ics;
9295
9296 list_for_each_entry_safe(cs, ics, &sections, list) {
9297 LIST_DEL(&cs->list);
9298 LIST_ADDQ(backup_sections, &cs->list);
9299 }
9300}
9301
9302void cfg_restore_sections(struct list *backup_sections)
9303{
9304 struct cfg_section *cs, *ics;
9305
9306 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9307 LIST_DEL(&cs->list);
9308 LIST_ADDQ(&sections, &cs->list);
9309 }
9310}
9311
Willy Tarreau659fbf02016-05-26 17:55:28 +02009312__attribute__((constructor))
9313static void cfgparse_init(void)
9314{
9315 /* Register internal sections */
9316 cfg_register_section("listen", cfg_parse_listen);
9317 cfg_register_section("frontend", cfg_parse_listen);
9318 cfg_register_section("backend", cfg_parse_listen);
9319 cfg_register_section("defaults", cfg_parse_listen);
9320 cfg_register_section("global", cfg_parse_global);
9321 cfg_register_section("userlist", cfg_parse_users);
9322 cfg_register_section("peers", cfg_parse_peers);
9323 cfg_register_section("mailers", cfg_parse_mailers);
9324 cfg_register_section("namespace_list", cfg_parse_netns);
9325 cfg_register_section("resolvers", cfg_parse_resolvers);
9326}
9327
David Carlier845efb52015-09-25 11:49:18 +01009328/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009329 * Local variables:
9330 * c-indent-level: 8
9331 * c-basic-offset: 8
9332 * End:
9333 */