blob: fc346b99fc0789332e738f337d6fc2ac70207f8a [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 Tarreau27a674e2009-08-17 07:23:33 +0200776 }
777 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200778 if (alertif_too_many_args(1, file, linenum, args, &err_code))
779 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200786 if (global.tune.maxrewrite < 0) {
787 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
790 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200791 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100792 else if (!strcmp(args[0], "tune.idletimer")) {
793 unsigned int idle;
794 const char *res;
795
William Lallemand1a748ae2015-05-19 16:37:23 +0200796 if (alertif_too_many_args(1, file, linenum, args, &err_code))
797 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
805 if (res) {
806 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
807 file, linenum, *res, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811
812 if (idle > 65535) {
813 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.idle_timer = idle;
818 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100819 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
821 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100822 if (global.tune.client_rcvbuf != 0) {
823 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT;
825 goto out;
826 }
827 if (*(args[1]) == 0) {
828 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 global.tune.client_rcvbuf = atol(args[1]);
833 }
834 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100837 if (global.tune.server_rcvbuf != 0) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT;
840 goto out;
841 }
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.server_rcvbuf = atol(args[1]);
848 }
849 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100852 if (global.tune.client_sndbuf != 0) {
853 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT;
855 goto out;
856 }
857 if (*(args[1]) == 0) {
858 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 global.tune.client_sndbuf = atol(args[1]);
863 }
864 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200865 if (alertif_too_many_args(1, file, linenum, args, &err_code))
866 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100867 if (global.tune.server_sndbuf != 0) {
868 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT;
870 goto out;
871 }
872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877 global.tune.server_sndbuf = atol(args[1]);
878 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200879 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200880 if (alertif_too_many_args(1, file, linenum, args, &err_code))
881 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200882 if (*(args[1]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887 global.tune.pipesize = atol(args[1]);
888 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100889 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200890 if (alertif_too_many_args(1, file, linenum, args, &err_code))
891 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100892 if (*(args[1]) == 0) {
893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
897 global.tune.cookie_len = atol(args[1]) + 1;
898 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200899 else if (!strcmp(args[0], "tune.http.logurilen")) {
900 if (alertif_too_many_args(1, file, linenum, args, &err_code))
901 goto out;
902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 global.tune.requri_len = atol(args[1]) + 1;
908 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200909 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200910 if (alertif_too_many_args(1, file, linenum, args, &err_code))
911 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200912 if (*(args[1]) == 0) {
913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200917 global.tune.max_http_hdr = atoi(args[1]);
918 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
919 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
920 file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200924 }
William Lallemandf3747832012-11-09 12:33:10 +0100925 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
927 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100928 if (*args[1]) {
929 global.tune.comp_maxlevel = atoi(args[1]);
930 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
931 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
932 file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 } else {
937 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
938 file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200943 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
944 if (*args[1]) {
945 global.tune.pattern_cache = atoi(args[1]);
946 if (global.tune.pattern_cache < 0) {
947 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
948 file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 } else {
953 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
954 file, linenum, args[0]);
955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
957 }
958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200960 if (alertif_too_many_args(1, file, linenum, args, &err_code))
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200963 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT;
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100972 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
973 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]);
974 err_code |= ERR_WARN;
975 goto out;
976 }
977
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200980 if (alertif_too_many_args(1, file, linenum, args, &err_code))
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200983 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT;
985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100992 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
993 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]);
994 err_code |= ERR_WARN;
995 goto out;
996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
Simon Horman98637e52014-06-20 12:30:16 +0900998 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200999 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1000 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001001 global.external_check = 1;
1002 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001003 /* user/group name handling */
1004 else if (!strcmp(args[0], "user")) {
1005 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1007 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001008 if (global.uid != 0) {
1009 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT;
1011 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001012 }
1013 errno = 0;
1014 ha_user = getpwnam(args[1]);
1015 if (ha_user != NULL) {
1016 global.uid = (int)ha_user->pw_uid;
1017 }
1018 else {
1019 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 +02001020 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001021 }
1022 }
1023 else if (!strcmp(args[0], "group")) {
1024 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001025 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1026 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001027 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001028 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT;
1030 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001031 }
1032 errno = 0;
1033 ha_group = getgrnam(args[1]);
1034 if (ha_group != NULL) {
1035 global.gid = (int)ha_group->gr_gid;
1036 }
1037 else {
1038 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 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001040 }
1041 }
1042 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001044 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 if (*(args[1]) == 0) {
1047 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 }
1051 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001052 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1053 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1054 file, linenum, args[0], LONGBITS, global.nbproc);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001060 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 if (global.maxconn != 0) {
1063 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 err_code |= ERR_ALERT;
1065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 }
1067 if (*(args[1]) == 0) {
1068 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 }
1072 global.maxconn = atol(args[1]);
1073#ifdef SYSTEM_MAXCONN
1074 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1075 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);
1076 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 }
1079#endif /* SYSTEM_MAXCONN */
1080 }
Emeric Brun850efd52014-01-29 12:24:34 +01001081 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001082 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1083 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 if (strcmp(args[1],"none") == 0)
1090 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1091 else if (strcmp(args[1],"required") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1093 else {
1094 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001099 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001100 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1101 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001102 if (global.cps_lim != 0) {
1103 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT;
1105 goto out;
1106 }
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 global.cps_lim = atol(args[1]);
1113 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001114 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001115 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1116 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001117 if (global.sps_lim != 0) {
1118 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT;
1120 goto out;
1121 }
1122 if (*(args[1]) == 0) {
1123 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
1126 }
1127 global.sps_lim = atol(args[1]);
1128 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001129 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001130 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1131 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001132 if (global.ssl_lim != 0) {
1133 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1134 err_code |= ERR_ALERT;
1135 goto out;
1136 }
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
1141 }
1142 global.ssl_lim = atol(args[1]);
1143 }
William Lallemandd85f9172012-11-09 17:05:39 +01001144 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152 global.comp_rate_lim = atoi(args[1]) * 1024;
1153 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001154 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001157 if (global.maxpipes != 0) {
1158 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT;
1160 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001161 }
1162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001166 }
1167 global.maxpipes = atol(args[1]);
1168 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001169 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001170 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1171 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001172 if (*(args[1]) == 0) {
1173 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
1176 }
William Lallemande3a7d992012-11-20 11:25:20 +01001177 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001178 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001179 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001188 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001189 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
1192 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001193 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001194
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 if (global.rlimit_nofile != 0) {
1199 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 }
1208 global.rlimit_nofile = atol(args[1]);
1209 }
1210 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 if (global.chroot != NULL) {
1214 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 if (*(args[1]) == 0) {
1219 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 }
1223 global.chroot = strdup(args[1]);
1224 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001225 else if (!strcmp(args[0], "description")) {
1226 int i, len=0;
1227 char *d;
1228
1229 if (!*args[1]) {
1230 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
Willy Tarreau348acfe2014-04-14 15:00:39 +02001236 for (i = 1; *args[i]; i++)
1237 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001238
1239 if (global.desc)
1240 free(global.desc);
1241
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001242 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001243
Willy Tarreau348acfe2014-04-14 15:00:39 +02001244 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1245 for (i = 2; *args[i]; i++)
1246 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001247 }
1248 else if (!strcmp(args[0], "node")) {
1249 int i;
1250 char c;
1251
William Lallemand1a748ae2015-05-19 16:37:23 +02001252 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1253 goto out;
1254
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001255 for (i=0; args[1][i]; i++) {
1256 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001257 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1258 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001259 break;
1260 }
1261
1262 if (!i || args[1][i]) {
1263 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1264 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1265 file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269
1270 if (global.node)
1271 free(global.node);
1272
1273 global.node = strdup(args[1]);
1274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001276 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 if (global.pidfile != NULL) {
1279 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT;
1281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
1283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 }
1288 global.pidfile = strdup(args[1]);
1289 }
Emeric Bruned760922010-10-22 17:59:25 +02001290 else if (!strcmp(args[0], "unix-bind")) {
1291 int cur_arg = 1;
1292 while (*(args[cur_arg])) {
1293 if (!strcmp(args[cur_arg], "prefix")) {
1294 if (global.unix_bind.prefix != NULL) {
1295 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1296 err_code |= ERR_ALERT;
1297 cur_arg += 2;
1298 continue;
1299 }
1300
1301 if (*(args[cur_arg+1]) == 0) {
1302 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1307 cur_arg += 2;
1308 continue;
1309 }
1310
1311 if (!strcmp(args[cur_arg], "mode")) {
1312
1313 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1314 cur_arg += 2;
1315 continue;
1316 }
1317
1318 if (!strcmp(args[cur_arg], "uid")) {
1319
1320 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1321 cur_arg += 2;
1322 continue;
1323 }
1324
1325 if (!strcmp(args[cur_arg], "gid")) {
1326
1327 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1328 cur_arg += 2;
1329 continue;
1330 }
1331
1332 if (!strcmp(args[cur_arg], "user")) {
1333 struct passwd *user;
1334
1335 user = getpwnam(args[cur_arg + 1]);
1336 if (!user) {
1337 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1338 file, linenum, args[0], args[cur_arg + 1 ]);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343 global.unix_bind.ux.uid = user->pw_uid;
1344 cur_arg += 2;
1345 continue;
1346 }
1347
1348 if (!strcmp(args[cur_arg], "group")) {
1349 struct group *group;
1350
1351 group = getgrnam(args[cur_arg + 1]);
1352 if (!group) {
1353 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1354 file, linenum, args[0], args[cur_arg + 1 ]);
1355 err_code |= ERR_ALERT | ERR_FATAL;
1356 goto out;
1357 }
1358
1359 global.unix_bind.ux.gid = group->gr_gid;
1360 cur_arg += 2;
1361 continue;
1362 }
1363
Willy Tarreaub48f9582011-09-05 01:17:06 +02001364 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001365 file, linenum, args[0]);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
1368 }
1369 }
William Lallemand0f99e342011-10-12 17:50:54 +02001370 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1371 /* delete previous herited or defined syslog servers */
1372 struct logsrv *back;
1373 struct logsrv *tmp;
1374
1375 if (*(args[1]) != 0) {
1376 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380
1381 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1382 LIST_DEL(&tmp->list);
1383 free(tmp);
1384 }
1385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001387 struct sockaddr_storage *sk;
1388 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001389 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001390 int arg = 0;
1391 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001392
William Lallemand1a748ae2015-05-19 16:37:23 +02001393 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1394 goto out;
1395
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (*(args[1]) == 0 || *(args[2]) == 0) {
1397 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
William Lallemand0f99e342011-10-12 17:50:54 +02001401
Vincent Bernat02779b62016-04-03 13:48:43 +02001402 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Willy Tarreau18324f52014-06-27 18:10:07 +02001404 /* just after the address, a length may be specified */
1405 if (strcmp(args[arg+2], "len") == 0) {
1406 len = atoi(args[arg+3]);
1407 if (len < 80 || len > 65535) {
1408 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1409 file, linenum, args[arg+3]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413 logsrv->maxlen = len;
1414
1415 /* skip these two args */
1416 arg += 2;
1417 }
1418 else
1419 logsrv->maxlen = MAX_SYSLOG_LEN;
1420
Christopher Faulet084aa962017-08-29 16:54:41 +02001421 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001422 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001423
Dragan Dosen1322d092015-09-22 16:05:32 +02001424 /* after the length, a format may be specified */
1425 if (strcmp(args[arg+2], "format") == 0) {
1426 logsrv->format = get_log_format(args[arg+3]);
1427 if (logsrv->format < 0) {
1428 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001430 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 goto out;
1432 }
1433
1434 /* skip these two args */
1435 arg += 2;
1436 }
1437
David Carlier97880bb2016-04-08 10:35:26 +01001438 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1439 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001440 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001441 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001442
Willy Tarreau18324f52014-06-27 18:10:07 +02001443 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001444 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001445 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001447 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
1449
William Lallemand0f99e342011-10-12 17:50:54 +02001450 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001451 if (*(args[arg+3])) {
1452 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001453 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001454 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001456 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 }
1458 }
1459
William Lallemand0f99e342011-10-12 17:50:54 +02001460 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 if (*(args[arg+4])) {
1462 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001463 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001464 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001466 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001467 }
1468 }
1469
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001470 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001471 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001472 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001474 free(logsrv);
1475 goto out;
1476 }
1477 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001478
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001479 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001480 if (port1 != port2) {
1481 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1482 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001483 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001484 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001485 goto out;
1486 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487
William Lallemand0f99e342011-10-12 17:50:54 +02001488 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001489 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001490 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
William Lallemand0f99e342011-10-12 17:50:54 +02001493 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001494 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001495 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1496 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001497
1498 if (global.log_send_hostname != NULL) {
1499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1500 err_code |= ERR_ALERT;
1501 goto out;
1502 }
1503
1504 if (*(args[1]))
1505 name = args[1];
1506 else
1507 name = hostname;
1508
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001509 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001510 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001511 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001512 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1513 if (global.server_state_base != NULL) {
1514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1515 err_code |= ERR_ALERT;
1516 goto out;
1517 }
1518
1519 if (!*(args[1])) {
1520 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1521 err_code |= ERR_FATAL;
1522 goto out;
1523 }
1524
1525 global.server_state_base = strdup(args[1]);
1526 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001527 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1528 if (global.server_state_file != NULL) {
1529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1530 err_code |= ERR_ALERT;
1531 goto out;
1532 }
1533
1534 if (!*(args[1])) {
1535 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1536 err_code |= ERR_FATAL;
1537 goto out;
1538 }
1539
1540 global.server_state_file = strdup(args[1]);
1541 }
Kevinm48936af2010-12-22 16:08:21 +00001542 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001543 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1544 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001545 if (*(args[1]) == 0) {
1546 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1547 err_code |= ERR_ALERT | ERR_FATAL;
1548 goto out;
1549 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001550 chunk_destroy(&global.log_tag);
1551 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001552 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001553 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001554 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1555 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001556 if (global.spread_checks != 0) {
1557 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001558 err_code |= ERR_ALERT;
1559 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 }
1561 if (*(args[1]) == 0) {
1562 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001565 }
1566 global.spread_checks = atol(args[1]);
1567 if (global.spread_checks < 0 || global.spread_checks > 50) {
1568 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001572 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1573 const char *err;
1574 unsigned int val;
1575
William Lallemand1a748ae2015-05-19 16:37:23 +02001576 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1577 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001578 if (*(args[1]) == 0) {
1579 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
1583
1584 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1585 if (err) {
1586 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 }
1589 global.max_spread_checks = val;
1590 if (global.max_spread_checks < 0) {
1591 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1592 err_code |= ERR_ALERT | ERR_FATAL;
1593 }
1594 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001595 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1596#ifdef USE_CPU_AFFINITY
1597 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001598 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001599 unsigned long cpus = 0;
1600
1601 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001602 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001603 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001604 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001605 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001606 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001607 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001608 proc = atol(args[1]);
1609 if (proc >= 1 && proc <= LONGBITS)
1610 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001611 }
1612
1613 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001614 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",
1615 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
1619
1620 cur_arg = 2;
1621 while (*args[cur_arg]) {
1622 unsigned int low, high;
1623
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001624 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001625 char *dash = strchr(args[cur_arg], '-');
1626
1627 low = high = str2uic(args[cur_arg]);
1628 if (dash)
1629 high = str2uic(dash + 1);
1630
1631 if (high < low) {
1632 unsigned int swap = low;
1633 low = high;
1634 high = swap;
1635 }
1636
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001637 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001638 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001639 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
1642 }
1643
1644 while (low <= high)
1645 cpus |= 1UL << low++;
1646 }
1647 else {
1648 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1649 file, linenum, args[0], args[cur_arg]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653 cur_arg++;
1654 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001655 for (i = 0; i < LONGBITS; i++)
1656 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001657 global.cpu_map[i] = cpus;
1658#else
1659 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662#endif
1663 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001664 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1665 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1666 goto out;
1667
1668 if (*(args[2]) == 0) {
1669 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
1672 }
1673
1674 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1675 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1676 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680 }
1681 else if (!strcmp(args[0], "unsetenv")) {
1682 int arg;
1683
1684 if (*(args[1]) == 0) {
1685 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 for (arg = 1; *args[arg]; arg++) {
1691 if (unsetenv(args[arg]) != 0) {
1692 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696 }
1697 }
1698 else if (!strcmp(args[0], "resetenv")) {
1699 extern char **environ;
1700 char **env = environ;
1701
1702 /* args contain variable names to keep, one per argument */
1703 while (*env) {
1704 int arg;
1705
1706 /* look for current variable in among all those we want to keep */
1707 for (arg = 1; *args[arg]; arg++) {
1708 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1709 (*env)[strlen(args[arg])] == '=')
1710 break;
1711 }
1712
1713 /* delete this variable */
1714 if (!*args[arg]) {
1715 char *delim = strchr(*env, '=');
1716
1717 if (!delim || delim - *env >= trash.size) {
1718 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721 }
1722
1723 memcpy(trash.str, *env, delim - *env);
1724 trash.str[delim - *env] = 0;
1725
1726 if (unsetenv(trash.str) != 0) {
1727 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731 }
1732 else
1733 env++;
1734 }
1735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001737 struct cfg_kw_list *kwl;
1738 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001739 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001740
1741 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1742 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1743 if (kwl->kw[index].section != CFG_GLOBAL)
1744 continue;
1745 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001746 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001747 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001748 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001750 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001751 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001752 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001753 err_code |= ERR_WARN;
1754 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001755 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
1758 }
1759 }
1760
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001762 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001764
Willy Tarreau058e9072009-07-20 09:30:05 +02001765 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001766 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001767 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768}
1769
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001770void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001772 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 defproxy.mode = PR_MODE_TCP;
1774 defproxy.state = PR_STNEW;
1775 defproxy.maxconn = cfg_maxpconn;
1776 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001777 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001778 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001779
Simon Horman66183002013-02-23 10:16:43 +09001780 defproxy.defsrv.check.inter = DEF_CHKINTR;
1781 defproxy.defsrv.check.fastinter = 0;
1782 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001783 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1784 defproxy.defsrv.agent.fastinter = 0;
1785 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001786 defproxy.defsrv.check.rise = DEF_RISETIME;
1787 defproxy.defsrv.check.fall = DEF_FALLTIME;
1788 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1789 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001790 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001791 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001792 defproxy.defsrv.maxqueue = 0;
1793 defproxy.defsrv.minconn = 0;
1794 defproxy.defsrv.maxconn = 0;
1795 defproxy.defsrv.slowstart = 0;
1796 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1797 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1798 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001799
1800 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001801 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802}
1803
Willy Tarreauade5ec42010-01-28 19:33:49 +01001804
Willy Tarreau63af98d2014-05-18 08:11:41 +02001805/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1806 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1807 * ERR_FATAL in case of error.
1808 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001809static int create_cond_regex_rule(const char *file, int line,
1810 struct proxy *px, int dir, int action, int flags,
1811 const char *cmd, const char *reg, const char *repl,
1812 const char **cond_start)
1813{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001814 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001815 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001817 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001818 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001819 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001820 int cs;
1821 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001822
1823 if (px == &defproxy) {
1824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001826 goto err;
1827 }
1828
1829 if (*reg == 0) {
1830 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001831 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001832 goto err;
1833 }
1834
Christopher Faulet898566e2016-10-26 11:06:28 +02001835 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837
Willy Tarreau5321c422010-01-28 20:35:13 +01001838 if (cond_start &&
1839 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001840 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1841 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1842 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001844 goto err;
1845 }
1846 }
1847 else if (cond_start && **cond_start) {
1848 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1849 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 goto err;
1852 }
1853
Willy Tarreau63af98d2014-05-18 08:11:41 +02001854 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001855 (dir == SMP_OPT_DIR_REQ) ?
1856 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1857 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1858 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001859
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001860 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001861 if (!preg) {
1862 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001864 goto err;
1865 }
1866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 cs = !(flags & REG_ICASE);
1868 cap = !(flags & REG_NOSUB);
1869 error = NULL;
1870 if (!regex_comp(reg, preg, cs, cap, &error)) {
1871 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1872 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001873 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874 goto err;
1875 }
1876
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001877 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001878 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879 if (repl && err) {
1880 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1881 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001882 ret_code |= ERR_ALERT | ERR_FATAL;
1883 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884 }
1885
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001886 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 ret_code |= ERR_WARN;
1888
1889 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001890
Willy Tarreau63af98d2014-05-18 08:11:41 +02001891 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001892 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893 err:
1894 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001895 free(errmsg);
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897}
1898
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899/*
William Lallemand51097192015-04-14 16:35:22 +02001900 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001901 * Returns the error code, 0 if OK, or any combination of :
1902 * - ERR_ABORT: must abort ASAP
1903 * - ERR_FATAL: we can continue parsing but not start the service
1904 * - ERR_WARN: a warning has been emitted
1905 * - ERR_ALERT: an alert has been emitted
1906 * Only the two first ones can stop processing, the two others are just
1907 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001909int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1910{
1911 static struct peers *curpeers = NULL;
1912 struct peer *newpeer = NULL;
1913 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001914 struct bind_conf *bind_conf;
1915 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001917 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001918
1919 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001920 if (!*args[1]) {
1921 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001922 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001923 goto out;
1924 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
William Lallemand6e62fb62015-04-28 16:55:23 +02001926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1927 goto out;
1928
Emeric Brun32da3c42010-09-23 18:39:19 +02001929 err = invalid_char(args[1]);
1930 if (err) {
1931 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1932 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001933 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001934 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001935 }
1936
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001937 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 /*
1939 * If there are two proxies with the same name only following
1940 * combinations are allowed:
1941 */
1942 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001943 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 +02001944 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001946 }
1947 }
1948
Vincent Bernat02779b62016-04-03 13:48:43 +02001949 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001950 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1951 err_code |= ERR_ALERT | ERR_ABORT;
1952 goto out;
1953 }
1954
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001955 curpeers->next = cfg_peers;
1956 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001957 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001958 curpeers->conf.line = linenum;
1959 curpeers->last_change = now.tv_sec;
1960 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001961 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001962 }
1963 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001964 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001965 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001966 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001967
1968 if (!*args[2]) {
1969 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1970 file, linenum, args[0]);
1971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
1973 }
1974
1975 err = invalid_char(args[1]);
1976 if (err) {
1977 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1978 file, linenum, *err, args[1]);
1979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
1981 }
1982
Vincent Bernat02779b62016-04-03 13:48:43 +02001983 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001984 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1985 err_code |= ERR_ALERT | ERR_ABORT;
1986 goto out;
1987 }
1988
1989 /* the peers are linked backwards first */
1990 curpeers->count++;
1991 newpeer->next = curpeers->remote;
1992 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001993 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001994 newpeer->conf.line = linenum;
1995
1996 newpeer->last_change = now.tv_sec;
1997 newpeer->id = strdup(args[1]);
1998
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001999 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002000 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002001 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002005
2006 proto = protocol_by_family(sk->ss_family);
2007 if (!proto || !proto->connect) {
2008 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2009 file, linenum, args[0], args[1]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002013
2014 if (port1 != port2) {
2015 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2016 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
2020
Willy Tarreau2aa38802013-02-20 19:20:59 +01002021 if (!port1) {
2022 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2023 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002027
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002029 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002030 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002031 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002032
Emeric Brun32da3c42010-09-23 18:39:19 +02002033 if (strcmp(newpeer->id, localpeer) == 0) {
2034 /* Current is local peer, it define a frontend */
2035 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002036 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002037
2038 if (!curpeers->peers_fe) {
2039 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2041 err_code |= ERR_ALERT | ERR_ABORT;
2042 goto out;
2043 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
Willy Tarreau237250c2011-07-29 01:49:03 +02002045 init_new_proxy(curpeers->peers_fe);
2046 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002048 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2049 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002050 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002051
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002052 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002053
Willy Tarreau902636f2013-03-10 19:44:48 +01002054 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2055 if (errmsg && *errmsg) {
2056 indent_msg(&errmsg, 2);
2057 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002058 }
2059 else
2060 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2061 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002062 err_code |= ERR_FATAL;
2063 goto out;
2064 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002065
2066 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002067 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002068 l->maxconn = curpeers->peers_fe->maxconn;
2069 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002070 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002071 l->analysers |= curpeers->peers_fe->fe_req_ana;
2072 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002073 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2074 global.maxsock += l->maxconn;
2075 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002076 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002077 else {
2078 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2079 file, linenum, args[0], args[1],
2080 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2081 err_code |= ERR_FATAL;
2082 goto out;
2083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
2085 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002086 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2087 curpeers->state = PR_STSTOPPED;
2088 }
2089 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2090 curpeers->state = PR_STNEW;
2091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 else if (*args[0] != 0) {
2093 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
2097
2098out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002099 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 return err_code;
2101}
2102
Baptiste Assmann325137d2015-04-13 23:40:55 +02002103/*
2104 * Parse a <resolvers> section.
2105 * Returns the error code, 0 if OK, or any combination of :
2106 * - ERR_ABORT: must abort ASAP
2107 * - ERR_FATAL: we can continue parsing but not start the service
2108 * - ERR_WARN: a warning has been emitted
2109 * - ERR_ALERT: an alert has been emitted
2110 * Only the two first ones can stop processing, the two others are just
2111 * indicators.
2112 */
2113int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2114{
2115 static struct dns_resolvers *curr_resolvers = NULL;
2116 struct dns_nameserver *newnameserver = NULL;
2117 const char *err;
2118 int err_code = 0;
2119 char *errmsg = NULL;
2120
2121 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2122 if (!*args[1]) {
2123 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 goto out;
2126 }
2127
2128 err = invalid_char(args[1]);
2129 if (err) {
2130 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2131 file, linenum, *err, args[0], args[1]);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2137 /* Error if two resolvers owns the same name */
2138 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2139 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2140 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2141 err_code |= ERR_ALERT | ERR_ABORT;
2142 }
2143 }
2144
Vincent Bernat02779b62016-04-03 13:48:43 +02002145 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002146 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2147 err_code |= ERR_ALERT | ERR_ABORT;
2148 goto out;
2149 }
2150
2151 /* default values */
2152 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2153 curr_resolvers->conf.file = strdup(file);
2154 curr_resolvers->conf.line = linenum;
2155 curr_resolvers->id = strdup(args[1]);
2156 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002157 /* default maximum response size */
2158 curr_resolvers->accepted_payload_size = 512;
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 Assmann686408b2017-08-18 10:15:42 +02002164 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002165 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002166 curr_resolvers->hold.valid = 10000;
2167 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002168 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002169 /* default resolution pool size */
2170 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002171 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002172 LIST_INIT(&curr_resolvers->resolution.curr);
2173 LIST_INIT(&curr_resolvers->resolution.wait);
2174 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002175 }
2176 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2177 struct sockaddr_storage *sk;
2178 int port1, port2;
2179 struct protocol *proto;
2180
2181 if (!*args[2]) {
2182 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2183 file, linenum, args[0]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187
2188 err = invalid_char(args[1]);
2189 if (err) {
2190 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2191 file, linenum, *err, args[1]);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
Baptiste Assmanna315c552015-11-02 22:55:49 +01002196 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2197 /* Error if two resolvers owns the same name */
2198 if (strcmp(newnameserver->id, args[1]) == 0) {
2199 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2200 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2201 err_code |= ERR_ALERT | ERR_FATAL;
2202 }
2203 }
2204
Vincent Bernat02779b62016-04-03 13:48:43 +02002205 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002206 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2207 err_code |= ERR_ALERT | ERR_ABORT;
2208 goto out;
2209 }
2210
2211 /* the nameservers are linked backward first */
2212 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2213 curr_resolvers->count_nameservers++;
2214 newnameserver->resolvers = curr_resolvers;
2215 newnameserver->conf.file = strdup(file);
2216 newnameserver->conf.line = linenum;
2217 newnameserver->id = strdup(args[1]);
2218
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002219 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002220 if (!sk) {
2221 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
2224 }
2225
2226 proto = protocol_by_family(sk->ss_family);
2227 if (!proto || !proto->connect) {
2228 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2229 file, linenum, args[0], args[1]);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234 if (port1 != port2) {
2235 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2236 file, linenum, args[0], args[1], args[2]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002241 if (!port1 && !port2) {
2242 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2243 file, linenum, args[0], args[1]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
Baptiste Assmann325137d2015-04-13 23:40:55 +02002248 newnameserver->addr = *sk;
2249 }
2250 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2251 const char *res;
2252 unsigned int time;
2253
2254 if (!*args[2]) {
2255 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2256 file, linenum, args[0]);
2257 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
2260 }
2261 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2262 if (res) {
2263 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2264 file, linenum, *res, args[0]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002268 if (strcmp(args[1], "nx") == 0)
2269 curr_resolvers->hold.nx = time;
2270 else if (strcmp(args[1], "other") == 0)
2271 curr_resolvers->hold.other = time;
2272 else if (strcmp(args[1], "refused") == 0)
2273 curr_resolvers->hold.refused = time;
2274 else if (strcmp(args[1], "timeout") == 0)
2275 curr_resolvers->hold.timeout = time;
2276 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002277 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002278 else if (strcmp(args[1], "obsolete") == 0)
2279 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002280 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002281 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002282 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
2285 }
2286
2287 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002288 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002289 int i = 0;
2290
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002291 if (!*args[1]) {
2292 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2293 file, linenum, args[0]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002297
2298 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002299 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2300 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2301 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
2305
2306 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002307 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002308 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2309 if (!*args[1]) {
2310 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2311 file, linenum, args[0]);
2312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
2314 }
2315 curr_resolvers->resolution_pool_size = atoi(args[1]);
2316 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002317 else if (strcmp(args[0], "resolve_retries") == 0) {
2318 if (!*args[1]) {
2319 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2320 file, linenum, args[0]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324 curr_resolvers->resolve_retries = atoi(args[1]);
2325 }
2326 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002327 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002328 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2329 file, linenum, args[0]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002333 else if (strcmp(args[1], "retry") == 0) {
2334 const char *res;
2335 unsigned int timeout_retry;
2336
2337 if (!*args[2]) {
2338 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2339 file, linenum, args[0], args[1]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2344 if (res) {
2345 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2346 file, linenum, *res, args[0], args[1]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 curr_resolvers->timeout.retry = timeout_retry;
2351 }
2352 else {
2353 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2354 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 } /* neither "nameserver" nor "resolvers" */
2359 else if (*args[0] != 0) {
2360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
2365 out:
2366 free(errmsg);
2367 return err_code;
2368}
Simon Horman0d16a402015-01-30 11:22:58 +09002369
2370/*
William Lallemand51097192015-04-14 16:35:22 +02002371 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002372 * Returns the error code, 0 if OK, or any combination of :
2373 * - ERR_ABORT: must abort ASAP
2374 * - ERR_FATAL: we can continue parsing but not start the service
2375 * - ERR_WARN: a warning has been emitted
2376 * - ERR_ALERT: an alert has been emitted
2377 * Only the two first ones can stop processing, the two others are just
2378 * indicators.
2379 */
2380int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2381{
2382 static struct mailers *curmailers = NULL;
2383 struct mailer *newmailer = NULL;
2384 const char *err;
2385 int err_code = 0;
2386 char *errmsg = NULL;
2387
2388 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2389 if (!*args[1]) {
2390 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394
2395 err = invalid_char(args[1]);
2396 if (err) {
2397 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2398 file, linenum, *err, args[0], args[1]);
2399 err_code |= ERR_ALERT | ERR_ABORT;
2400 goto out;
2401 }
2402
2403 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2404 /*
2405 * If there are two proxies with the same name only following
2406 * combinations are allowed:
2407 */
2408 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002409 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 +09002410 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002412 }
2413 }
2414
Vincent Bernat02779b62016-04-03 13:48:43 +02002415 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2417 err_code |= ERR_ALERT | ERR_ABORT;
2418 goto out;
2419 }
2420
2421 curmailers->next = mailers;
2422 mailers = curmailers;
2423 curmailers->conf.file = strdup(file);
2424 curmailers->conf.line = linenum;
2425 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002426 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2427 * But need enough time so that timeouts don't occur
2428 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002429 }
2430 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2431 struct sockaddr_storage *sk;
2432 int port1, port2;
2433 struct protocol *proto;
2434
2435 if (!*args[2]) {
2436 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2437 file, linenum, args[0]);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
2441
2442 err = invalid_char(args[1]);
2443 if (err) {
2444 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2445 file, linenum, *err, args[1]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
Vincent Bernat02779b62016-04-03 13:48:43 +02002450 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002451 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
2455
2456 /* the mailers are linked backwards first */
2457 curmailers->count++;
2458 newmailer->next = curmailers->mailer_list;
2459 curmailers->mailer_list = newmailer;
2460 newmailer->mailers = curmailers;
2461 newmailer->conf.file = strdup(file);
2462 newmailer->conf.line = linenum;
2463
2464 newmailer->id = strdup(args[1]);
2465
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002466 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002467 if (!sk) {
2468 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472
2473 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002474 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2475 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002476 file, linenum, args[0], args[1]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481 if (port1 != port2) {
2482 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2483 file, linenum, args[0], args[1], args[2]);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
2488 if (!port1) {
2489 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2490 file, linenum, args[0], args[1], args[2]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
2495 newmailer->addr = *sk;
2496 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002497 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002498 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002499 }
2500 else if (strcmp(args[0], "timeout") == 0) {
2501 if (!*args[1]) {
2502 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2503 file, linenum, args[0]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 else if (strcmp(args[1], "mail") == 0) {
2508 const char *res;
2509 unsigned int timeout_mail;
2510 if (!*args[2]) {
2511 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2512 file, linenum, args[0], args[1]);
2513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
2516 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2517 if (res) {
2518 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2519 file, linenum, *res, args[0]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523 if (timeout_mail <= 0) {
2524 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528 curmailers->timeout.mail = timeout_mail;
2529 } else {
2530 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2531 file, linenum, args[0], args[1]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535 }
Simon Horman0d16a402015-01-30 11:22:58 +09002536 else if (*args[0] != 0) {
2537 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
2540 }
2541
2542out:
2543 free(errmsg);
2544 return err_code;
2545}
2546
Simon Horman9dc49962015-01-30 11:22:59 +09002547static void free_email_alert(struct proxy *p)
2548{
2549 free(p->email_alert.mailers.name);
2550 p->email_alert.mailers.name = NULL;
2551 free(p->email_alert.from);
2552 p->email_alert.from = NULL;
2553 free(p->email_alert.to);
2554 p->email_alert.to = NULL;
2555 free(p->email_alert.myhostname);
2556 p->email_alert.myhostname = NULL;
2557}
2558
Willy Tarreau3842f002009-06-14 11:39:52 +02002559int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560{
2561 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002562 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002563 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002564 int rc;
2565 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002566 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002567 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002568 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002569 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002570 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571
Willy Tarreau977b8e42006-12-29 14:19:17 +01002572 if (!strcmp(args[0], "listen"))
2573 rc = PR_CAP_LISTEN;
2574 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002575 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002576 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002577 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 else
2579 rc = PR_CAP_NONE;
2580
2581 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 if (!*args[1]) {
2583 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002584 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_ABORT;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002589
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002590 err = invalid_char(args[1]);
2591 if (err) {
2592 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2593 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002595 }
2596
Willy Tarreau8f50b682015-05-26 11:45:02 +02002597 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2598 if (curproxy) {
2599 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2600 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2601 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002603 }
2604
Vincent Bernat02779b62016-04-03 13:48:43 +02002605 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_ABORT;
2608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002610
Willy Tarreau97cb7802010-01-03 20:23:58 +01002611 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 curproxy->next = proxy;
2613 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002614 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2615 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002616 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002618 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002619 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620
William Lallemand6e62fb62015-04-28 16:55:23 +02002621 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2622 if (curproxy->cap & PR_CAP_FE)
2623 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 }
2626
2627 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002628 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002629 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002630
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002633 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002634 curproxy->no_options = defproxy.no_options;
2635 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002636 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002637 curproxy->except_net = defproxy.except_net;
2638 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002639 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002640 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002642 if (defproxy.fwdfor_hdr_len) {
2643 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2644 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2645 }
2646
Willy Tarreaub86db342009-11-30 11:50:16 +01002647 if (defproxy.orgto_hdr_len) {
2648 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2649 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2650 }
2651
Mark Lamourinec2247f02012-01-04 13:02:01 -05002652 if (defproxy.server_id_hdr_len) {
2653 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2654 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2655 }
2656
Willy Tarreau977b8e42006-12-29 14:19:17 +01002657 if (curproxy->cap & PR_CAP_FE) {
2658 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002659 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002660 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002661
2662 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002663 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2664 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665
2666 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002670 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002671 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 curproxy->fullconn = defproxy.fullconn;
2673 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002674 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002675 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002677 if (defproxy.check_req) {
2678 curproxy->check_req = calloc(1, defproxy.check_len);
2679 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2680 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002681 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002683 if (defproxy.expect_str) {
2684 curproxy->expect_str = strdup(defproxy.expect_str);
2685 if (defproxy.expect_regex) {
2686 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002687 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2688 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002689 }
2690 }
2691
Willy Tarreau67402132012-05-31 20:40:20 +02002692 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 if (defproxy.cookie_name)
2694 curproxy->cookie_name = strdup(defproxy.cookie_name);
2695 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002696
2697 if (defproxy.dyncookie_key)
2698 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002699 if (defproxy.cookie_domain)
2700 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002701
Willy Tarreau31936852010-10-06 16:59:56 +02002702 if (defproxy.cookie_maxidle)
2703 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2704
2705 if (defproxy.cookie_maxlife)
2706 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2707
Emeric Brun647caf12009-06-30 17:57:00 +02002708 if (defproxy.rdp_cookie_name)
2709 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2710 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2711
Willy Tarreau01732802007-11-01 22:48:15 +01002712 if (defproxy.url_param_name)
2713 curproxy->url_param_name = strdup(defproxy.url_param_name);
2714 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002715
Benoitaffb4812009-03-25 13:02:10 +01002716 if (defproxy.hh_name)
2717 curproxy->hh_name = strdup(defproxy.hh_name);
2718 curproxy->hh_len = defproxy.hh_len;
2719 curproxy->hh_match_domain = defproxy.hh_match_domain;
2720
Willy Tarreauef9a3602012-12-08 22:29:20 +01002721 if (defproxy.conn_src.iface_name)
2722 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2723 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002724 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002725#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002726 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002727#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002728 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002731 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 if (defproxy.capture_name)
2733 curproxy->capture_name = strdup(defproxy.capture_name);
2734 curproxy->capture_namelen = defproxy.capture_namelen;
2735 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002739 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002740 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002741 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002742 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002743 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 curproxy->mon_net = defproxy.mon_net;
2745 curproxy->mon_mask = defproxy.mon_mask;
2746 if (defproxy.monitor_uri)
2747 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2748 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002749 if (defproxy.defbe.name)
2750 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002751
2752 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002753 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2754 if (curproxy->conf.logformat_string &&
2755 curproxy->conf.logformat_string != default_http_log_format &&
2756 curproxy->conf.logformat_string != default_tcp_log_format &&
2757 curproxy->conf.logformat_string != clf_http_log_format)
2758 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2759
2760 if (defproxy.conf.lfs_file) {
2761 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2762 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2763 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002764
2765 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2766 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2767 if (curproxy->conf.logformat_sd_string &&
2768 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2769 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2770
2771 if (defproxy.conf.lfsd_file) {
2772 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2773 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775 }
2776
2777 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002778 curproxy->timeout.connect = defproxy.timeout.connect;
2779 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002780 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002781 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002782 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002783 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002784 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002785 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002786 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002787 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788 }
2789
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002791 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002792
2793 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002794 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002795 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002796 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002797 LIST_INIT(&node->list);
2798 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2799 }
2800
Willy Tarreau62a61232013-04-12 18:13:46 +02002801 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2802 if (curproxy->conf.uniqueid_format_string)
2803 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2804
Dragan Dosen43885c72015-10-01 13:18:13 +02002805 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002806
Willy Tarreau62a61232013-04-12 18:13:46 +02002807 if (defproxy.conf.uif_file) {
2808 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2809 curproxy->conf.uif_line = defproxy.conf.uif_line;
2810 }
William Lallemanda73203e2012-03-12 12:48:57 +01002811
2812 /* copy default header unique id */
2813 if (defproxy.header_unique_id)
2814 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2815
William Lallemand82fe75c2012-10-23 10:25:10 +02002816 /* default compression options */
2817 if (defproxy.comp != NULL) {
2818 curproxy->comp = calloc(1, sizeof(struct comp));
2819 curproxy->comp->algos = defproxy.comp->algos;
2820 curproxy->comp->types = defproxy.comp->types;
2821 }
2822
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002824 curproxy->conf.used_listener_id = EB_ROOT;
2825 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002826
Simon Horman98637e52014-06-20 12:30:16 +09002827 if (defproxy.check_path)
2828 curproxy->check_path = strdup(defproxy.check_path);
2829 if (defproxy.check_command)
2830 curproxy->check_command = strdup(defproxy.check_command);
2831
Simon Horman9dc49962015-01-30 11:22:59 +09002832 if (defproxy.email_alert.mailers.name)
2833 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2834 if (defproxy.email_alert.from)
2835 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2836 if (defproxy.email_alert.to)
2837 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2838 if (defproxy.email_alert.myhostname)
2839 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002840 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002841 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002842
Willy Tarreau93893792009-07-23 13:19:11 +02002843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
2845 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2846 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002847 /* FIXME-20070101: we should do this too at the end of the
2848 * config parsing to free all default values.
2849 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002850 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2851 err_code |= ERR_ABORT;
2852 goto out;
2853 }
2854
Willy Tarreaua534fea2008-08-03 12:19:50 +02002855 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002856 free(defproxy.check_command);
2857 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002858 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002859 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002860 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002861 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002862 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002863 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002864 free(defproxy.capture_name);
2865 free(defproxy.monitor_uri);
2866 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002867 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002868 free(defproxy.fwdfor_hdr_name);
2869 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002870 free(defproxy.orgto_hdr_name);
2871 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002872 free(defproxy.server_id_hdr_name);
2873 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002874 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002875 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002876 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002877 free(defproxy.expect_regex);
2878 defproxy.expect_regex = NULL;
2879 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002880
Willy Tarreau62a61232013-04-12 18:13:46 +02002881 if (defproxy.conf.logformat_string != default_http_log_format &&
2882 defproxy.conf.logformat_string != default_tcp_log_format &&
2883 defproxy.conf.logformat_string != clf_http_log_format)
2884 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002885
Willy Tarreau62a61232013-04-12 18:13:46 +02002886 free(defproxy.conf.uniqueid_format_string);
2887 free(defproxy.conf.lfs_file);
2888 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002889 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002890 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002891
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002892 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2893 free(defproxy.conf.logformat_sd_string);
2894 free(defproxy.conf.lfsd_file);
2895
Willy Tarreaua534fea2008-08-03 12:19:50 +02002896 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002897 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002898
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 /* we cannot free uri_auth because it might already be used */
2900 init_default_instance();
2901 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002902 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2903 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002904 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 }
2907 else if (curproxy == NULL) {
2908 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002912
2913 /* update the current file and line being parsed */
2914 curproxy->conf.args.file = curproxy->conf.file;
2915 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002916
2917 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002918 if (!strcmp(args[0], "server") ||
2919 !strcmp(args[0], "default-server") ||
2920 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002921 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2922 if (err_code & ERR_FATAL)
2923 goto out;
2924 }
2925 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002926 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002927 int cur_arg;
2928
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 if (curproxy == &defproxy) {
2930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936
Willy Tarreau24709282013-03-10 21:32:12 +01002937 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002938 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002943
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002944 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002945
2946 /* use default settings for unix sockets */
2947 bind_conf->ux.uid = global.unix_bind.ux.uid;
2948 bind_conf->ux.gid = global.unix_bind.ux.gid;
2949 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002950
2951 /* NOTE: the following line might create several listeners if there
2952 * are comma-separated IPs or port ranges. So all further processing
2953 * will have to be applied to all listeners created after last_listen.
2954 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002955 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2956 if (errmsg && *errmsg) {
2957 indent_msg(&errmsg, 2);
2958 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002959 }
2960 else
2961 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2962 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002966
Willy Tarreau4348fad2012-09-20 16:48:07 +02002967 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2968 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002969 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002970 }
2971
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002972 cur_arg = 2;
2973 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002974 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002975 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002976 char *err;
2977
Willy Tarreau26982662012-09-12 23:17:10 +02002978 kw = bind_find_kw(args[cur_arg]);
2979 if (kw) {
2980 char *err = NULL;
2981 int code;
2982
2983 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002984 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2985 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002986 cur_arg += 1 + kw->skip ;
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
Willy Tarreau4348fad2012-09-20 16:48:07 +02002991 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002992 err_code |= code;
2993
2994 if (code) {
2995 if (err && *err) {
2996 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002997 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002998 }
2999 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003000 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3001 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003002 if (code & ERR_FATAL) {
3003 free(err);
3004 cur_arg += 1 + kw->skip;
3005 goto out;
3006 }
3007 }
3008 free(err);
3009 cur_arg += 1 + kw->skip;
3010 continue;
3011 }
3012
Willy Tarreau8638f482012-09-18 18:01:17 +02003013 err = NULL;
3014 if (!bind_dumped) {
3015 bind_dump_kws(&err);
3016 indent_msg(&err, 4);
3017 bind_dumped = 1;
3018 }
3019
3020 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3021 file, linenum, args[0], args[1], args[cur_arg],
3022 err ? " Registered keywords :" : "", err ? err : "");
3023 free(err);
3024
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003027 }
Willy Tarreau93893792009-07-23 13:19:11 +02003028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
3030 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003031 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003037 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003039
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 /* flush useless bits */
3041 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003044 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003045 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047
William Lallemanddf1425a2015-04-28 20:17:49 +02003048 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3049 goto out;
3050
Willy Tarreau1c47f852006-07-09 08:22:27 +02003051 if (!*args[1]) {
3052 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3053 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003056 }
3057
Willy Tarreaua534fea2008-08-03 12:19:50 +02003058 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003059 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003060 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003061 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003062 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3063
Willy Tarreau93893792009-07-23 13:19:11 +02003064 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003067 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3068 goto out;
3069
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3071 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3072 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3073 else {
3074 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 }
3078 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003079 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003080 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003081
3082 if (curproxy == &defproxy) {
3083 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003087 }
3088
William Lallemanddf1425a2015-04-28 20:17:49 +02003089 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3090 goto out;
3091
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003092 if (!*args[1]) {
3093 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3094 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003097 }
3098
3099 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003100 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003101 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003102
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003103 if (curproxy->uuid <= 0) {
3104 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003105 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003108 }
3109
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003110 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3111 if (node) {
3112 struct proxy *target = container_of(node, struct proxy, conf.id);
3113 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3114 file, linenum, proxy_type_str(curproxy), curproxy->id,
3115 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003120 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003121 else if (!strcmp(args[0], "description")) {
3122 int i, len=0;
3123 char *d;
3124
Cyril Bonté99ed3272010-01-24 23:29:44 +01003125 if (curproxy == &defproxy) {
3126 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3127 file, linenum, args[0]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003132 if (!*args[1]) {
3133 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3134 file, linenum, args[0]);
3135 return -1;
3136 }
3137
Willy Tarreau348acfe2014-04-14 15:00:39 +02003138 for (i = 1; *args[i]; i++)
3139 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003140
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003141 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003142 curproxy->desc = d;
3143
Willy Tarreau348acfe2014-04-14 15:00:39 +02003144 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3145 for (i = 2; *args[i]; i++)
3146 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003147
3148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003150 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 curproxy->state = PR_STSTOPPED;
3153 }
3154 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003155 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 curproxy->state = PR_STNEW;
3158 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003159 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3160 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003161 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003162
3163 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003164 unsigned int low, high;
3165
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003166 if (strcmp(args[cur_arg], "all") == 0) {
3167 set = 0;
3168 break;
3169 }
3170 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003171 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003172 }
3173 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003174 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003175 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003176 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003177 char *dash = strchr(args[cur_arg], '-');
3178
3179 low = high = str2uic(args[cur_arg]);
3180 if (dash)
3181 high = str2uic(dash + 1);
3182
3183 if (high < low) {
3184 unsigned int swap = low;
3185 low = high;
3186 high = swap;
3187 }
3188
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003189 if (low < 1 || high > LONGBITS) {
3190 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3191 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003194 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003195 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003196 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003197 }
3198 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003199 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3200 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003203 }
3204 cur_arg++;
3205 }
3206 curproxy->bind_proc = set;
3207 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003208 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003209 if (curproxy == &defproxy) {
3210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003213 }
3214
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003215 err = invalid_char(args[1]);
3216 if (err) {
3217 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3218 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003220 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003221 }
3222
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003223 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003224 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3225 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003228 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003229 }
3230 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3231
3232 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3233 err_code |= ERR_WARN;
3234
3235 if (*(args[1]) == 0) {
3236 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3237 file, linenum, args[0]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241 free(curproxy->dyncookie_key);
3242 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3245 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246
Willy Tarreau977b8e42006-12-29 14:19:17 +01003247 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003249
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 if (*(args[1]) == 0) {
3251 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003256
Willy Tarreau67402132012-05-31 20:40:20 +02003257 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003258 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003259 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003260 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 curproxy->cookie_name = strdup(args[1]);
3262 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003263
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 cur_arg = 2;
3265 while (*(args[cur_arg])) {
3266 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003267 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 }
3269 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003270 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
3272 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003273 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 }
3275 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003276 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
3278 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003279 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003281 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003282 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003285 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003287 else if (!strcmp(args[cur_arg], "httponly")) {
3288 curproxy->ck_opts |= PR_CK_HTTPONLY;
3289 }
3290 else if (!strcmp(args[cur_arg], "secure")) {
3291 curproxy->ck_opts |= PR_CK_SECURE;
3292 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003293 else if (!strcmp(args[cur_arg], "domain")) {
3294 if (!*args[cur_arg + 1]) {
3295 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3296 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003299 }
3300
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003301 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003302 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003303 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3304 " dots nor does not start with a dot."
3305 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003306 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003307 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003308 }
3309
3310 err = invalid_domainchar(args[cur_arg + 1]);
3311 if (err) {
3312 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3313 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003316 }
3317
Willy Tarreau68a897b2009-12-03 23:28:34 +01003318 if (!curproxy->cookie_domain) {
3319 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3320 } else {
3321 /* one domain was already specified, add another one by
3322 * building the string which will be returned along with
3323 * the cookie.
3324 */
3325 char *new_ptr;
3326 int new_len = strlen(curproxy->cookie_domain) +
3327 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3328 new_ptr = malloc(new_len);
3329 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3330 free(curproxy->cookie_domain);
3331 curproxy->cookie_domain = new_ptr;
3332 }
Willy Tarreau31936852010-10-06 16:59:56 +02003333 cur_arg++;
3334 }
3335 else if (!strcmp(args[cur_arg], "maxidle")) {
3336 unsigned int maxidle;
3337 const char *res;
3338
3339 if (!*args[cur_arg + 1]) {
3340 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3341 file, linenum, args[cur_arg]);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345
3346 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3347 if (res) {
3348 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3349 file, linenum, *res, args[cur_arg]);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353 curproxy->cookie_maxidle = maxidle;
3354 cur_arg++;
3355 }
3356 else if (!strcmp(args[cur_arg], "maxlife")) {
3357 unsigned int maxlife;
3358 const char *res;
3359
3360 if (!*args[cur_arg + 1]) {
3361 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3362 file, linenum, args[cur_arg]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366
3367 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3368 if (res) {
3369 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3370 file, linenum, *res, args[cur_arg]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003375 cur_arg++;
3376 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003377 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003378
3379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3380 err_code |= ERR_WARN;
3381 curproxy->ck_opts |= PR_CK_DYNAMIC;
3382 }
3383
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003385 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 +02003386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
3390 cur_arg++;
3391 }
Willy Tarreau67402132012-05-31 20:40:20 +02003392 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3394 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397
Willy Tarreau67402132012-05-31 20:40:20 +02003398 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3400 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003403
Willy Tarreau67402132012-05-31 20:40:20 +02003404 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003405 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3406 file, linenum);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003410 else if (!strcmp(args[0], "email-alert")) {
3411 if (*(args[1]) == 0) {
3412 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3413 file, linenum, args[0]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417
3418 if (!strcmp(args[1], "from")) {
3419 if (*(args[1]) == 0) {
3420 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3421 file, linenum, args[1]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425 free(curproxy->email_alert.from);
3426 curproxy->email_alert.from = strdup(args[2]);
3427 }
3428 else if (!strcmp(args[1], "mailers")) {
3429 if (*(args[1]) == 0) {
3430 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3431 file, linenum, args[1]);
3432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
3434 }
3435 free(curproxy->email_alert.mailers.name);
3436 curproxy->email_alert.mailers.name = strdup(args[2]);
3437 }
3438 else if (!strcmp(args[1], "myhostname")) {
3439 if (*(args[1]) == 0) {
3440 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3441 file, linenum, args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 free(curproxy->email_alert.myhostname);
3446 curproxy->email_alert.myhostname = strdup(args[2]);
3447 }
Simon Horman64e34162015-02-06 11:11:57 +09003448 else if (!strcmp(args[1], "level")) {
3449 curproxy->email_alert.level = get_log_level(args[2]);
3450 if (curproxy->email_alert.level < 0) {
3451 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3452 file, linenum, args[1], args[2]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 }
Simon Horman9dc49962015-01-30 11:22:59 +09003457 else if (!strcmp(args[1], "to")) {
3458 if (*(args[1]) == 0) {
3459 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3460 file, linenum, args[1]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464 free(curproxy->email_alert.to);
3465 curproxy->email_alert.to = strdup(args[2]);
3466 }
3467 else {
3468 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3469 file, linenum, args[1]);
3470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
3472 }
Simon Horman64e34162015-02-06 11:11:57 +09003473 /* Indicate that the email_alert is at least partially configured */
3474 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003475 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003476 else if (!strcmp(args[0], "external-check")) {
3477 if (*(args[1]) == 0) {
3478 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3479 file, linenum, args[0]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
3483
3484 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003485 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003486 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003487 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003488 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3489 file, linenum, args[1]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
3493 free(curproxy->check_command);
3494 curproxy->check_command = strdup(args[2]);
3495 }
3496 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003497 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003498 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003499 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003500 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3501 file, linenum, args[1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 free(curproxy->check_path);
3506 curproxy->check_path = strdup(args[2]);
3507 }
3508 else {
3509 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3510 file, linenum, args[1]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003515 else if (!strcmp(args[0], "persist")) { /* persist */
3516 if (*(args[1]) == 0) {
3517 Alert("parsing [%s:%d] : missing persist method.\n",
3518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003521 }
3522
3523 if (!strncmp(args[1], "rdp-cookie", 10)) {
3524 curproxy->options2 |= PR_O2_RDPC_PRST;
3525
Emeric Brunb982a3d2010-01-04 15:45:53 +01003526 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003527 const char *beg, *end;
3528
3529 beg = args[1] + 11;
3530 end = strchr(beg, ')');
3531
William Lallemanddf1425a2015-04-28 20:17:49 +02003532 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3533 goto out;
3534
Emeric Brun647caf12009-06-30 17:57:00 +02003535 if (!end || end == beg) {
3536 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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
3542 free(curproxy->rdp_cookie_name);
3543 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3544 curproxy->rdp_cookie_len = end-beg;
3545 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003546 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003547 free(curproxy->rdp_cookie_name);
3548 curproxy->rdp_cookie_name = strdup("msts");
3549 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3550 }
3551 else { /* syntax */
3552 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3553 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003556 }
3557 }
3558 else {
3559 Alert("parsing [%s:%d] : unknown persist method.\n",
3560 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003563 }
3564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003566 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003570 else if (!strcmp(args[0], "load-server-state-from-file")) {
3571 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3572 err_code |= ERR_WARN;
3573 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3574 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3575 }
3576 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3577 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3578 }
3579 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3580 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3581 }
3582 else {
3583 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3584 file, linenum, args[0], args[1]);
3585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
3587 }
3588 }
3589 else if (!strcmp(args[0], "server-state-file-name")) {
3590 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3591 err_code |= ERR_WARN;
3592 if (*(args[1]) == 0) {
3593 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3594 file, linenum, args[0]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598 else if (!strcmp(args[1], "use-backend-name"))
3599 curproxy->server_state_file_name = strdup(curproxy->id);
3600 else
3601 curproxy->server_state_file_name = strdup(args[1]);
3602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003604 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003606
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003608 if (curproxy == &defproxy) {
3609 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
3612 }
3613
William Lallemand1a748ae2015-05-19 16:37:23 +02003614 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3615 goto out;
3616
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 if (*(args[4]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003623 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 curproxy->capture_name = strdup(args[2]);
3625 curproxy->capture_namelen = strlen(curproxy->capture_name);
3626 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 curproxy->to_log |= LW_COOKIE;
3628 }
3629 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3630 struct cap_hdr *hdr;
3631
3632 if (curproxy == &defproxy) {
3633 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 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
3637
William Lallemand1a748ae2015-05-19 16:37:23 +02003638 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3639 goto out;
3640
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3642 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3643 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
3647
Vincent Bernat02779b62016-04-03 13:48:43 +02003648 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 hdr->next = curproxy->req_cap;
3650 hdr->name = strdup(args[3]);
3651 hdr->namelen = strlen(args[3]);
3652 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003653 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 hdr->index = curproxy->nb_req_cap++;
3655 curproxy->req_cap = hdr;
3656 curproxy->to_log |= LW_REQHDR;
3657 }
3658 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3659 struct cap_hdr *hdr;
3660
3661 if (curproxy == &defproxy) {
3662 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 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
3666
William Lallemand1a748ae2015-05-19 16:37:23 +02003667 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3668 goto out;
3669
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3671 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003676 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 hdr->next = curproxy->rsp_cap;
3678 hdr->name = strdup(args[3]);
3679 hdr->namelen = strlen(args[3]);
3680 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003681 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 hdr->index = curproxy->nb_rsp_cap++;
3683 curproxy->rsp_cap = hdr;
3684 curproxy->to_log |= LW_RSPHDR;
3685 }
3686 else {
3687 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 }
3692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003694 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003696
William Lallemanddf1425a2015-04-28 20:17:49 +02003697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3698 goto out;
3699
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 if (*(args[1]) == 0) {
3701 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706 curproxy->conn_retries = atol(args[1]);
3707 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003708 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003709 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003710
3711 if (curproxy == &defproxy) {
3712 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716
Willy Tarreau20b0de52012-12-24 15:45:22 +01003717 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003718 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003719 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3720 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3721 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3722 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003723 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 +01003724 file, linenum, args[0]);
3725 err_code |= ERR_WARN;
3726 }
3727
Willy Tarreauff011f22011-01-06 17:51:27 +01003728 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003729
Willy Tarreauff011f22011-01-06 17:51:27 +01003730 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003731 err_code |= ERR_ALERT | ERR_ABORT;
3732 goto out;
3733 }
3734
Willy Tarreau5002f572014-04-23 01:32:02 +02003735 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003736 err_code |= warnif_cond_conflicts(rule->cond,
3737 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3738 file, linenum);
3739
Willy Tarreauff011f22011-01-06 17:51:27 +01003740 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003741 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003742 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003743 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003744
3745 if (curproxy == &defproxy) {
3746 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
3749 }
3750
3751 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003752 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003753 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3754 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003755 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3756 file, linenum, args[0]);
3757 err_code |= ERR_WARN;
3758 }
3759
3760 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3761
3762 if (!rule) {
3763 err_code |= ERR_ALERT | ERR_ABORT;
3764 goto out;
3765 }
3766
3767 err_code |= warnif_cond_conflicts(rule->cond,
3768 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3769 file, linenum);
3770
3771 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3772 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003773 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3774 /* set the header name and length into the proxy structure */
3775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3776 err_code |= ERR_WARN;
3777
3778 if (!*args[1]) {
3779 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3780 file, linenum, args[0]);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784
3785 /* set the desired header name */
3786 free(curproxy->server_id_hdr_name);
3787 curproxy->server_id_hdr_name = strdup(args[1]);
3788 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3789 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003790 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003791 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003792
Willy Tarreaub099aca2008-10-12 17:26:37 +02003793 if (curproxy == &defproxy) {
3794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003797 }
3798
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003799 /* emulate "block" using "http-request block". Since these rules are supposed to
3800 * be processed before all http-request rules, we put them into their own list
3801 * and will insert them at the end.
3802 */
3803 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3804 if (!rule) {
3805 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003806 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003807 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003808 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3809 err_code |= warnif_cond_conflicts(rule->cond,
3810 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3811 file, linenum);
3812 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003813
3814 if (!already_warned(WARN_BLOCK_DEPRECATED))
3815 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]);
3816
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003817 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003818 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003819 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003820
Cyril Bonté99ed3272010-01-24 23:29:44 +01003821 if (curproxy == &defproxy) {
3822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826
Willy Tarreaube4653b2015-05-28 15:26:58 +02003827 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003828 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3829 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003832 }
3833
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003834 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003835 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003836 err_code |= warnif_cond_conflicts(rule->cond,
3837 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3838 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003839 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003840 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003841 struct switching_rule *rule;
3842
Willy Tarreaub099aca2008-10-12 17:26:37 +02003843 if (curproxy == &defproxy) {
3844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003847 }
3848
Willy Tarreau55ea7572007-06-17 19:56:27 +02003849 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851
3852 if (*(args[1]) == 0) {
3853 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003856 }
3857
Willy Tarreauf51658d2014-04-23 01:21:56 +02003858 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3859 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3860 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3861 file, linenum, errmsg);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003865
Willy Tarreauf51658d2014-04-23 01:21:56 +02003866 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003867 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003868 else if (*args[2]) {
3869 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3870 file, linenum, args[2]);
3871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
3873 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003874
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003875 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003876 if (!rule) {
3877 Alert("Out of memory error.\n");
3878 goto out;
3879 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003880 rule->cond = cond;
3881 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003882 rule->line = linenum;
3883 rule->file = strdup(file);
3884 if (!rule->file) {
3885 Alert("Out of memory error.\n");
3886 goto out;
3887 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003888 LIST_INIT(&rule->list);
3889 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3890 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003891 else if (strcmp(args[0], "use-server") == 0) {
3892 struct server_rule *rule;
3893
3894 if (curproxy == &defproxy) {
3895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
3898 }
3899
3900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3901 err_code |= ERR_WARN;
3902
3903 if (*(args[1]) == 0) {
3904 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
3907 }
3908
3909 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3910 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3911 file, linenum, args[0]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003916 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3917 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3918 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003923 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003924
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003925 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003926 rule->cond = cond;
3927 rule->srv.name = strdup(args[1]);
3928 LIST_INIT(&rule->list);
3929 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3930 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3931 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003932 else if ((!strcmp(args[0], "force-persist")) ||
3933 (!strcmp(args[0], "ignore-persist"))) {
3934 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003935
3936 if (curproxy == &defproxy) {
3937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
3941
3942 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3943 err_code |= ERR_WARN;
3944
Willy Tarreauef6494c2010-01-28 17:12:36 +01003945 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003946 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3947 file, linenum, args[0]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003952 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3953 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3954 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003959 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3960 * where force-persist is applied.
3961 */
3962 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003963
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003964 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003965 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003966 if (!strcmp(args[0], "force-persist")) {
3967 rule->type = PERSIST_TYPE_FORCE;
3968 } else {
3969 rule->type = PERSIST_TYPE_IGNORE;
3970 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003971 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003972 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003973 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003974 else if (!strcmp(args[0], "stick-table")) {
3975 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003976 struct proxy *other;
3977
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003978 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003979 if (other) {
3980 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3981 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003985
Emeric Brun32da3c42010-09-23 18:39:19 +02003986 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003987 curproxy->table.type = (unsigned int)-1;
3988 while (*args[myidx]) {
3989 const char *err;
3990
3991 if (strcmp(args[myidx], "size") == 0) {
3992 myidx++;
3993 if (!*(args[myidx])) {
3994 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3995 file, linenum, args[myidx-1]);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
3999 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4000 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4001 file, linenum, *err, args[myidx-1]);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004005 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004006 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004007 else if (strcmp(args[myidx], "peers") == 0) {
4008 myidx++;
Godbach50523162013-12-11 19:48:57 +08004009 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004010 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4011 file, linenum, args[myidx-1]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Godbach50523162013-12-11 19:48:57 +08004014 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004015 curproxy->table.peers.name = strdup(args[myidx++]);
4016 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 else if (strcmp(args[myidx], "expire") == 0) {
4018 myidx++;
4019 if (!*(args[myidx])) {
4020 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4021 file, linenum, args[myidx-1]);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024 }
4025 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4026 if (err) {
4027 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4028 file, linenum, *err, args[myidx-1]);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004032 if (val > INT_MAX) {
4033 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4034 file, linenum, val);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004038 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004039 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004040 }
4041 else if (strcmp(args[myidx], "nopurge") == 0) {
4042 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004043 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004044 }
4045 else if (strcmp(args[myidx], "type") == 0) {
4046 myidx++;
4047 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4048 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4049 file, linenum, args[myidx]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004053 /* myidx already points to next arg */
4054 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004055 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004056 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004057 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004058
4059 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004060 nw = args[myidx];
4061 while (*nw) {
4062 /* the "store" keyword supports a comma-separated list */
4063 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004064 sa = NULL; /* store arg */
4065 while (*nw && *nw != ',') {
4066 if (*nw == '(') {
4067 *nw = 0;
4068 sa = ++nw;
4069 while (*nw != ')') {
4070 if (!*nw) {
4071 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4072 file, linenum, args[0], cw);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 nw++;
4077 }
4078 *nw = '\0';
4079 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004080 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004081 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004082 if (*nw)
4083 *nw++ = '\0';
4084 type = stktable_get_data_type(cw);
4085 if (type < 0) {
4086 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4087 file, linenum, args[0], cw);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
Willy Tarreauac782882010-06-20 10:41:54 +02004091
4092 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4093 switch (err) {
4094 case PE_NONE: break;
4095 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004096 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4097 file, linenum, args[0], cw);
4098 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004099 break;
4100
4101 case PE_ARG_MISSING:
4102 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4103 file, linenum, args[0], cw);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106
4107 case PE_ARG_NOT_USED:
4108 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4109 file, linenum, args[0], cw);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112
4113 default:
4114 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4115 file, linenum, args[0], cw);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004118 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004119 }
4120 myidx++;
4121 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004122 else {
4123 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4124 file, linenum, args[myidx]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004127 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004128 }
4129
4130 if (!curproxy->table.size) {
4131 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4132 file, linenum);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136
4137 if (curproxy->table.type == (unsigned int)-1) {
4138 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4139 file, linenum);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 }
4144 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004146 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004147 int myidx = 0;
4148 const char *name = NULL;
4149 int flags;
4150
4151 if (curproxy == &defproxy) {
4152 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156
4157 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4158 err_code |= ERR_WARN;
4159 goto out;
4160 }
4161
4162 myidx++;
4163 if ((strcmp(args[myidx], "store") == 0) ||
4164 (strcmp(args[myidx], "store-request") == 0)) {
4165 myidx++;
4166 flags = STK_IS_STORE;
4167 }
4168 else if (strcmp(args[myidx], "store-response") == 0) {
4169 myidx++;
4170 flags = STK_IS_STORE | STK_ON_RSP;
4171 }
4172 else if (strcmp(args[myidx], "match") == 0) {
4173 myidx++;
4174 flags = STK_IS_MATCH;
4175 }
4176 else if (strcmp(args[myidx], "on") == 0) {
4177 myidx++;
4178 flags = STK_IS_MATCH | STK_IS_STORE;
4179 }
4180 else {
4181 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
4186 if (*(args[myidx]) == 0) {
4187 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004192 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004193 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004194 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004195 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198 }
4199
4200 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004201 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4202 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4203 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004204 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004205 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004206 goto out;
4207 }
4208 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004209 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4210 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4211 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004212 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004213 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 goto out;
4215 }
4216 }
4217
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004218 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004219 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004220
Emeric Brunb982a3d2010-01-04 15:45:53 +01004221 if (strcmp(args[myidx], "table") == 0) {
4222 myidx++;
4223 name = args[myidx++];
4224 }
4225
Willy Tarreauef6494c2010-01-28 17:12:36 +01004226 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004227 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4228 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4229 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004230 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004231 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004232 goto out;
4233 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004234 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004235 else if (*(args[myidx])) {
4236 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4237 file, linenum, args[0], args[myidx]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004239 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004240 goto out;
4241 }
Emeric Brun97679e72010-09-23 17:56:44 +02004242 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004243 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004244 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004245 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004246
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004247 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004248 rule->cond = cond;
4249 rule->expr = expr;
4250 rule->flags = flags;
4251 rule->table.name = name ? strdup(name) : NULL;
4252 LIST_INIT(&rule->list);
4253 if (flags & STK_ON_RSP)
4254 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4255 else
4256 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 else if (!strcmp(args[0], "stats")) {
4259 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4260 curproxy->uri_auth = NULL; /* we must detach from the default config */
4261
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004262 if (!*args[1]) {
4263 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004264 } else if (!strcmp(args[1], "admin")) {
4265 struct stats_admin_rule *rule;
4266
4267 if (curproxy == &defproxy) {
4268 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
4273 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4274 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
4277 }
4278
4279 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4280 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4281 file, linenum, args[0], args[1]);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004285 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4286 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4287 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004292 err_code |= warnif_cond_conflicts(cond,
4293 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4294 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004295
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004296 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004297 rule->cond = cond;
4298 LIST_INIT(&rule->list);
4299 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 } else if (!strcmp(args[1], "uri")) {
4301 if (*(args[2]) == 0) {
4302 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_ABORT;
4308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 }
4310 } else if (!strcmp(args[1], "realm")) {
4311 if (*(args[2]) == 0) {
4312 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_ABORT;
4318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004320 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004321 unsigned interval;
4322
4323 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4324 if (err) {
4325 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4326 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004329 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4330 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_ABORT;
4332 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004333 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004334 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004335 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004336
4337 if (curproxy == &defproxy) {
4338 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342
4343 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4344 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4345 err_code |= ERR_ALERT | ERR_ABORT;
4346 goto out;
4347 }
4348
Willy Tarreauff011f22011-01-06 17:51:27 +01004349 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004350 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004351 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4352 file, linenum, args[0]);
4353 err_code |= ERR_WARN;
4354 }
4355
Willy Tarreauff011f22011-01-06 17:51:27 +01004356 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004357
Willy Tarreauff011f22011-01-06 17:51:27 +01004358 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004359 err_code |= ERR_ALERT | ERR_ABORT;
4360 goto out;
4361 }
4362
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004363 err_code |= warnif_cond_conflicts(rule->cond,
4364 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4365 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004366 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004367
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 } else if (!strcmp(args[1], "auth")) {
4369 if (*(args[2]) == 0) {
4370 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4374 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 }
4378 } else if (!strcmp(args[1], "scope")) {
4379 if (*(args[2]) == 0) {
4380 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_ABORT;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 } else if (!strcmp(args[1], "enable")) {
4389 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_ABORT;
4392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004394 } else if (!strcmp(args[1], "hide-version")) {
4395 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_ABORT;
4398 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004399 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004400 } else if (!strcmp(args[1], "show-legends")) {
4401 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4403 err_code |= ERR_ALERT | ERR_ABORT;
4404 goto out;
4405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004406 } else if (!strcmp(args[1], "show-node")) {
4407
4408 if (*args[2]) {
4409 int i;
4410 char c;
4411
4412 for (i=0; args[2][i]; i++) {
4413 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004414 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4415 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004416 break;
4417 }
4418
4419 if (!i || args[2][i]) {
4420 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4421 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4422 file, linenum, args[0], args[1]);
4423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
4425 }
4426 }
4427
4428 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4429 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4430 err_code |= ERR_ALERT | ERR_ABORT;
4431 goto out;
4432 }
4433 } else if (!strcmp(args[1], "show-desc")) {
4434 char *desc = NULL;
4435
4436 if (*args[2]) {
4437 int i, len=0;
4438 char *d;
4439
Willy Tarreau348acfe2014-04-14 15:00:39 +02004440 for (i = 2; *args[i]; i++)
4441 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004442
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004443 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004444
Willy Tarreau348acfe2014-04-14 15:00:39 +02004445 d += snprintf(d, desc + len - d, "%s", args[2]);
4446 for (i = 3; *args[i]; i++)
4447 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004448 }
4449
4450 if (!*args[2] && !global.desc)
4451 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4452 file, linenum, args[1]);
4453 else {
4454 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4455 free(desc);
4456 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4457 err_code |= ERR_ALERT | ERR_ABORT;
4458 goto out;
4459 }
4460 free(desc);
4461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004463stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004464 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 +01004465 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 }
4469 }
4470 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004471 int optnum;
4472
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004473 if (*(args[1]) == '\0') {
4474 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004479
4480 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4481 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004482 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4483 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4484 file, linenum, cfg_opts[optnum].name);
4485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
4487 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004488 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4489 goto out;
4490
Willy Tarreau93893792009-07-23 13:19:11 +02004491 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4492 err_code |= ERR_WARN;
4493 goto out;
4494 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004495
Willy Tarreau3842f002009-06-14 11:39:52 +02004496 curproxy->no_options &= ~cfg_opts[optnum].val;
4497 curproxy->options &= ~cfg_opts[optnum].val;
4498
4499 switch (kwm) {
4500 case KWM_STD:
4501 curproxy->options |= cfg_opts[optnum].val;
4502 break;
4503 case KWM_NO:
4504 curproxy->no_options |= cfg_opts[optnum].val;
4505 break;
4506 case KWM_DEF: /* already cleared */
4507 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004508 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004509
Willy Tarreau93893792009-07-23 13:19:11 +02004510 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004511 }
4512 }
4513
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004514 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4515 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004516 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4517 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4518 file, linenum, cfg_opts2[optnum].name);
4519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
4521 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004522 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4523 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004524 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4525 err_code |= ERR_WARN;
4526 goto out;
4527 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004528
Willy Tarreau3842f002009-06-14 11:39:52 +02004529 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4530 curproxy->options2 &= ~cfg_opts2[optnum].val;
4531
4532 switch (kwm) {
4533 case KWM_STD:
4534 curproxy->options2 |= cfg_opts2[optnum].val;
4535 break;
4536 case KWM_NO:
4537 curproxy->no_options2 |= cfg_opts2[optnum].val;
4538 break;
4539 case KWM_DEF: /* already cleared */
4540 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004541 }
Willy Tarreau93893792009-07-23 13:19:11 +02004542 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004543 }
4544 }
4545
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004546 /* HTTP options override each other. They can be cancelled using
4547 * "no option xxx" which only switches to default mode if the mode
4548 * was this one (useful for cancelling options set in defaults
4549 * sections).
4550 */
4551 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004552 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4553 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004554 if (kwm == KWM_STD) {
4555 curproxy->options &= ~PR_O_HTTP_MODE;
4556 curproxy->options |= PR_O_HTTP_PCL;
4557 goto out;
4558 }
4559 else if (kwm == KWM_NO) {
4560 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4561 curproxy->options &= ~PR_O_HTTP_MODE;
4562 goto out;
4563 }
4564 }
4565 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004566 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4567 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004568 if (kwm == KWM_STD) {
4569 curproxy->options &= ~PR_O_HTTP_MODE;
4570 curproxy->options |= PR_O_HTTP_FCL;
4571 goto out;
4572 }
4573 else if (kwm == KWM_NO) {
4574 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4575 curproxy->options &= ~PR_O_HTTP_MODE;
4576 goto out;
4577 }
4578 }
4579 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004580 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4581 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004582 if (kwm == KWM_STD) {
4583 curproxy->options &= ~PR_O_HTTP_MODE;
4584 curproxy->options |= PR_O_HTTP_SCL;
4585 goto out;
4586 }
4587 else if (kwm == KWM_NO) {
4588 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4589 curproxy->options &= ~PR_O_HTTP_MODE;
4590 goto out;
4591 }
4592 }
4593 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004594 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4595 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004596 if (kwm == KWM_STD) {
4597 curproxy->options &= ~PR_O_HTTP_MODE;
4598 curproxy->options |= PR_O_HTTP_KAL;
4599 goto out;
4600 }
4601 else if (kwm == KWM_NO) {
4602 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4603 curproxy->options &= ~PR_O_HTTP_MODE;
4604 goto out;
4605 }
4606 }
4607 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004608 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4609 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004610 if (kwm == KWM_STD) {
4611 curproxy->options &= ~PR_O_HTTP_MODE;
4612 curproxy->options |= PR_O_HTTP_TUN;
4613 goto out;
4614 }
4615 else if (kwm == KWM_NO) {
4616 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4617 curproxy->options &= ~PR_O_HTTP_MODE;
4618 goto out;
4619 }
4620 }
4621
Joseph Lynch726ab712015-05-11 23:25:34 -07004622 /* Redispatch can take an integer argument that control when the
4623 * resispatch occurs. All values are relative to the retries option.
4624 * This can be cancelled using "no option xxx".
4625 */
4626 if (strcmp(args[1], "redispatch") == 0) {
4627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4628 err_code |= ERR_WARN;
4629 goto out;
4630 }
4631
4632 curproxy->no_options &= ~PR_O_REDISP;
4633 curproxy->options &= ~PR_O_REDISP;
4634
4635 switch (kwm) {
4636 case KWM_STD:
4637 curproxy->options |= PR_O_REDISP;
4638 curproxy->redispatch_after = -1;
4639 if(*args[2]) {
4640 curproxy->redispatch_after = atol(args[2]);
4641 }
4642 break;
4643 case KWM_NO:
4644 curproxy->no_options |= PR_O_REDISP;
4645 curproxy->redispatch_after = 0;
4646 break;
4647 case KWM_DEF: /* already cleared */
4648 break;
4649 }
4650 goto out;
4651 }
4652
Willy Tarreau3842f002009-06-14 11:39:52 +02004653 if (kwm != KWM_STD) {
4654 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004655 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004658 }
4659
Emeric Brun3a058f32009-06-30 18:26:00 +02004660 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004661 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004663 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004664 if (*(args[2]) != '\0') {
4665 if (!strcmp(args[2], "clf")) {
4666 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004667 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004668 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004669 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004672 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004673 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4674 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004675 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004676 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4677 char *oldlogformat = "log-format";
4678 char *clflogformat = "";
4679
4680 if (curproxy->conf.logformat_string == default_http_log_format)
4681 oldlogformat = "option httplog";
4682 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4683 oldlogformat = "option tcplog";
4684 else if (curproxy->conf.logformat_string == clf_http_log_format)
4685 oldlogformat = "option httplog clf";
4686 if (logformat == clf_http_log_format)
4687 clflogformat = " clf";
4688 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4689 file, linenum, clflogformat, oldlogformat);
4690 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004691 if (curproxy->conf.logformat_string != default_http_log_format &&
4692 curproxy->conf.logformat_string != default_tcp_log_format &&
4693 curproxy->conf.logformat_string != clf_http_log_format)
4694 free(curproxy->conf.logformat_string);
4695 curproxy->conf.logformat_string = logformat;
4696
4697 free(curproxy->conf.lfs_file);
4698 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4699 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004700 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004701 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004702 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4703 char *oldlogformat = "log-format";
4704
4705 if (curproxy->conf.logformat_string == default_http_log_format)
4706 oldlogformat = "option httplog";
4707 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4708 oldlogformat = "option tcplog";
4709 else if (curproxy->conf.logformat_string == clf_http_log_format)
4710 oldlogformat = "option httplog clf";
4711 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4712 file, linenum, oldlogformat);
4713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004715 if (curproxy->conf.logformat_string != default_http_log_format &&
4716 curproxy->conf.logformat_string != default_tcp_log_format &&
4717 curproxy->conf.logformat_string != clf_http_log_format)
4718 free(curproxy->conf.logformat_string);
4719 curproxy->conf.logformat_string = default_tcp_log_format;
4720
4721 free(curproxy->conf.lfs_file);
4722 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4723 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004724
4725 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4726 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004729 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004730 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004731 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004732
William Lallemanddf1425a2015-04-28 20:17:49 +02004733 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4734 goto out;
4735
Willy Tarreau13943ab2006-12-31 00:24:10 +01004736 if (curproxy->cap & PR_CAP_FE)
4737 curproxy->options |= PR_O_TCP_CLI_KA;
4738 if (curproxy->cap & PR_CAP_BE)
4739 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
4741 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004743 err_code |= ERR_WARN;
4744
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004746 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004747 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004748 curproxy->options2 &= ~PR_O2_CHK_ANY;
4749 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 if (!*args[2]) { /* no argument */
4751 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4752 curproxy->check_len = strlen(DEF_CHECK_REQ);
4753 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004754 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004755 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004757 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004759 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 if (*args[4])
4761 reqlen += strlen(args[4]);
4762 else
4763 reqlen += strlen("HTTP/1.0");
4764
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004765 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004767 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004769 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4770 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004771 }
4772 else if (!strcmp(args[1], "ssl-hello-chk")) {
4773 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004775 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004776
Willy Tarreaua534fea2008-08-03 12:19:50 +02004777 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004778 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004779 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004780 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004781
4782 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
Willy Tarreau23677902007-05-08 23:50:35 +02004785 else if (!strcmp(args[1], "smtpchk")) {
4786 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004787 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004788 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004789 curproxy->options2 &= ~PR_O2_CHK_ANY;
4790 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004791
4792 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4793 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4794 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4795 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4796 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4797 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004798 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004799 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4800 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4801 } else {
4802 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4803 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4804 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4805 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4806 }
4807 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004808 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4809 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004810 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004811 else if (!strcmp(args[1], "pgsql-check")) {
4812 /* use PostgreSQL request to check servers' health */
4813 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4814 err_code |= ERR_WARN;
4815
4816 free(curproxy->check_req);
4817 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004818 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004819 curproxy->options2 |= PR_O2_PGSQL_CHK;
4820
4821 if (*(args[2])) {
4822 int cur_arg = 2;
4823
4824 while (*(args[cur_arg])) {
4825 if (strcmp(args[cur_arg], "user") == 0) {
4826 char * packet;
4827 uint32_t packet_len;
4828 uint32_t pv;
4829
4830 /* suboption header - needs additional argument for it */
4831 if (*(args[cur_arg+1]) == 0) {
4832 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4833 file, linenum, args[0], args[1], args[cur_arg]);
4834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
4836 }
4837
4838 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4839 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4840 pv = htonl(0x30000); /* protocol version 3.0 */
4841
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004842 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004843
4844 memcpy(packet + 4, &pv, 4);
4845
4846 /* copy "user" */
4847 memcpy(packet + 8, "user", 4);
4848
4849 /* copy username */
4850 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4851
4852 free(curproxy->check_req);
4853 curproxy->check_req = packet;
4854 curproxy->check_len = packet_len;
4855
4856 packet_len = htonl(packet_len);
4857 memcpy(packet, &packet_len, 4);
4858 cur_arg += 2;
4859 } else {
4860 /* unknown suboption - catchall */
4861 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4862 file, linenum, args[0], args[1]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866 } /* end while loop */
4867 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004868 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4869 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004870 }
4871
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004872 else if (!strcmp(args[1], "redis-check")) {
4873 /* use REDIS PING request to check servers' health */
4874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4875 err_code |= ERR_WARN;
4876
4877 free(curproxy->check_req);
4878 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004879 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004880 curproxy->options2 |= PR_O2_REDIS_CHK;
4881
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004882 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004883 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4884 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004885
4886 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4887 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004888 }
4889
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004890 else if (!strcmp(args[1], "mysql-check")) {
4891 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004892 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4893 err_code |= ERR_WARN;
4894
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004895 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004896 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004897 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004898 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004899
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004900 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004901 * const char mysql40_client_auth_pkt[] = {
4902 * "\x0e\x00\x00" // packet length
4903 * "\x01" // packet number
4904 * "\x00\x00" // client capabilities
4905 * "\x00\x00\x01" // max packet
4906 * "haproxy\x00" // username (null terminated string)
4907 * "\x00" // filler (always 0x00)
4908 * "\x01\x00\x00" // packet length
4909 * "\x00" // packet number
4910 * "\x01" // COM_QUIT command
4911 * };
4912 */
4913
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004914 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4915 * const char mysql41_client_auth_pkt[] = {
4916 * "\x0e\x00\x00\" // packet length
4917 * "\x01" // packet number
4918 * "\x00\x00\x00\x00" // client capabilities
4919 * "\x00\x00\x00\x01" // max packet
4920 * "\x21" // character set (UTF-8)
4921 * char[23] // All zeroes
4922 * "haproxy\x00" // username (null terminated string)
4923 * "\x00" // filler (always 0x00)
4924 * "\x01\x00\x00" // packet length
4925 * "\x00" // packet number
4926 * "\x01" // COM_QUIT command
4927 * };
4928 */
4929
4930
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004931 if (*(args[2])) {
4932 int cur_arg = 2;
4933
4934 while (*(args[cur_arg])) {
4935 if (strcmp(args[cur_arg], "user") == 0) {
4936 char *mysqluser;
4937 int packetlen, reqlen, userlen;
4938
4939 /* suboption header - needs additional argument for it */
4940 if (*(args[cur_arg+1]) == 0) {
4941 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4942 file, linenum, args[0], args[1], args[cur_arg]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946 mysqluser = args[cur_arg + 1];
4947 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004948
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004949 if (*(args[cur_arg+2])) {
4950 if (!strcmp(args[cur_arg+2], "post-41")) {
4951 packetlen = userlen + 7 + 27;
4952 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004953
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004954 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004955 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004956 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004957
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004958 snprintf(curproxy->check_req, 4, "%c%c%c",
4959 ((unsigned char) packetlen & 0xff),
4960 ((unsigned char) (packetlen >> 8) & 0xff),
4961 ((unsigned char) (packetlen >> 16) & 0xff));
4962
4963 curproxy->check_req[3] = 1;
4964 curproxy->check_req[5] = 130;
4965 curproxy->check_req[11] = 1;
4966 curproxy->check_req[12] = 33;
4967 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4968 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4969 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4970 cur_arg += 3;
4971 } else {
4972 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
4976 } else {
4977 packetlen = userlen + 7;
4978 reqlen = packetlen + 9;
4979
4980 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004981 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004982 curproxy->check_len = reqlen;
4983
4984 snprintf(curproxy->check_req, 4, "%c%c%c",
4985 ((unsigned char) packetlen & 0xff),
4986 ((unsigned char) (packetlen >> 8) & 0xff),
4987 ((unsigned char) (packetlen >> 16) & 0xff));
4988
4989 curproxy->check_req[3] = 1;
4990 curproxy->check_req[5] = 128;
4991 curproxy->check_req[8] = 1;
4992 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4993 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4994 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4995 cur_arg += 2;
4996 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004997 } else {
4998 /* unknown suboption - catchall */
4999 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5000 file, linenum, args[0], args[1]);
5001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
5004 } /* end while loop */
5005 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005006 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005007 else if (!strcmp(args[1], "ldap-check")) {
5008 /* use LDAP request to check servers' health */
5009 free(curproxy->check_req);
5010 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005011 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005012 curproxy->options2 |= PR_O2_LDAP_CHK;
5013
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005014 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005015 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5016 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005017 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5018 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005019 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005020 else if (!strcmp(args[1], "spop-check")) {
5021 if (curproxy == &defproxy) {
5022 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5023 file, linenum, args[0], args[1]);
5024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
5026 }
5027 if (curproxy->cap & PR_CAP_FE) {
5028 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5029 file, linenum, args[0], args[1]);
5030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
5033
5034 /* use SPOE request to check servers' health */
5035 free(curproxy->check_req);
5036 curproxy->check_req = NULL;
5037 curproxy->options2 &= ~PR_O2_CHK_ANY;
5038 curproxy->options2 |= PR_O2_SPOP_CHK;
5039
Christopher Faulet8ef75252017-02-20 22:56:03 +01005040 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005041 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
5044 }
5045 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5046 goto out;
5047 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005048 else if (!strcmp(args[1], "tcp-check")) {
5049 /* use raw TCPCHK send/expect to check servers' health */
5050 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5051 err_code |= ERR_WARN;
5052
5053 free(curproxy->check_req);
5054 curproxy->check_req = NULL;
5055 curproxy->options2 &= ~PR_O2_CHK_ANY;
5056 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005057 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5058 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005059 }
Simon Horman98637e52014-06-20 12:30:16 +09005060 else if (!strcmp(args[1], "external-check")) {
5061 /* excute an external command to check servers' health */
5062 free(curproxy->check_req);
5063 curproxy->check_req = NULL;
5064 curproxy->options2 &= ~PR_O2_CHK_ANY;
5065 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005066 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5067 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005068 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005069 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005070 int cur_arg;
5071
5072 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5073 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005074 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005075
Willy Tarreau87cf5142011-08-19 22:57:24 +02005076 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005077
5078 free(curproxy->fwdfor_hdr_name);
5079 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5080 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5081
5082 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5083 cur_arg = 2;
5084 while (*(args[cur_arg])) {
5085 if (!strcmp(args[cur_arg], "except")) {
5086 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005087 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005088 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5089 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005092 }
5093 /* flush useless bits */
5094 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005095 cur_arg += 2;
5096 } else if (!strcmp(args[cur_arg], "header")) {
5097 /* suboption header - needs additional argument for it */
5098 if (*(args[cur_arg+1]) == 0) {
5099 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5100 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005103 }
5104 free(curproxy->fwdfor_hdr_name);
5105 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5106 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5107 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005108 } else if (!strcmp(args[cur_arg], "if-none")) {
5109 curproxy->options &= ~PR_O_FF_ALWAYS;
5110 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005111 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005112 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005113 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005114 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005117 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005118 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005119 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005120 else if (!strcmp(args[1], "originalto")) {
5121 int cur_arg;
5122
5123 /* insert x-original-to field, but not for the IP address listed as an except.
5124 * set default options (ie: bitfield, header name, etc)
5125 */
5126
5127 curproxy->options |= PR_O_ORGTO;
5128
5129 free(curproxy->orgto_hdr_name);
5130 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5131 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5132
Willy Tarreau87cf5142011-08-19 22:57:24 +02005133 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005134 cur_arg = 2;
5135 while (*(args[cur_arg])) {
5136 if (!strcmp(args[cur_arg], "except")) {
5137 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005138 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 +02005139 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5140 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005143 }
5144 /* flush useless bits */
5145 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5146 cur_arg += 2;
5147 } else if (!strcmp(args[cur_arg], "header")) {
5148 /* suboption header - needs additional argument for it */
5149 if (*(args[cur_arg+1]) == 0) {
5150 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5151 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005154 }
5155 free(curproxy->orgto_hdr_name);
5156 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5157 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5158 cur_arg += 2;
5159 } else {
5160 /* unknown suboption - catchall */
5161 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5162 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005165 }
5166 } /* end while loop */
5167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 else {
5169 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005175 else if (!strcmp(args[0], "default_backend")) {
5176 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005178
5179 if (*(args[1]) == 0) {
5180 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005183 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005184 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005185 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005186
5187 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5188 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005193
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005194 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5195 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 +01005196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 /* enable reconnections to dispatch */
5199 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005200
5201 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005204 else if (!strcmp(args[0], "http-reuse")) {
5205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5206 err_code |= ERR_WARN;
5207
5208 if (strcmp(args[1], "never") == 0) {
5209 /* enable a graceful server shutdown on an HTTP 404 response */
5210 curproxy->options &= ~PR_O_REUSE_MASK;
5211 curproxy->options |= PR_O_REUSE_NEVR;
5212 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5213 goto out;
5214 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005215 else if (strcmp(args[1], "safe") == 0) {
5216 /* enable a graceful server shutdown on an HTTP 404 response */
5217 curproxy->options &= ~PR_O_REUSE_MASK;
5218 curproxy->options |= PR_O_REUSE_SAFE;
5219 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5220 goto out;
5221 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005222 else if (strcmp(args[1], "aggressive") == 0) {
5223 curproxy->options &= ~PR_O_REUSE_MASK;
5224 curproxy->options |= PR_O_REUSE_AGGR;
5225 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5226 goto out;
5227 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005228 else if (strcmp(args[1], "always") == 0) {
5229 /* enable a graceful server shutdown on an HTTP 404 response */
5230 curproxy->options &= ~PR_O_REUSE_MASK;
5231 curproxy->options |= PR_O_REUSE_ALWS;
5232 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5233 goto out;
5234 }
5235 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005236 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
5240 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005241 else if (!strcmp(args[0], "http-check")) {
5242 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005244
5245 if (strcmp(args[1], "disable-on-404") == 0) {
5246 /* enable a graceful server shutdown on an HTTP 404 response */
5247 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005248 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5249 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005250 }
Willy Tarreauef781042010-01-27 11:53:01 +01005251 else if (strcmp(args[1], "send-state") == 0) {
5252 /* enable emission of the apparent state of a server in HTTP checks */
5253 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005254 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5255 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005256 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005257 else if (strcmp(args[1], "expect") == 0) {
5258 const char *ptr_arg;
5259 int cur_arg;
5260
5261 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5262 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266
5267 cur_arg = 2;
5268 /* consider exclamation marks, sole or at the beginning of a word */
5269 while (*(ptr_arg = args[cur_arg])) {
5270 while (*ptr_arg == '!') {
5271 curproxy->options2 ^= PR_O2_EXP_INV;
5272 ptr_arg++;
5273 }
5274 if (*ptr_arg)
5275 break;
5276 cur_arg++;
5277 }
5278 /* now ptr_arg points to the beginning of a word past any possible
5279 * exclamation mark, and cur_arg is the argument which holds this word.
5280 */
5281 if (strcmp(ptr_arg, "status") == 0) {
5282 if (!*(args[cur_arg + 1])) {
5283 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5284 file, linenum, args[0], args[1], ptr_arg);
5285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
5287 }
5288 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005289 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005290 curproxy->expect_str = strdup(args[cur_arg + 1]);
5291 }
5292 else if (strcmp(ptr_arg, "string") == 0) {
5293 if (!*(args[cur_arg + 1])) {
5294 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5295 file, linenum, args[0], args[1], ptr_arg);
5296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298 }
5299 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005300 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005301 curproxy->expect_str = strdup(args[cur_arg + 1]);
5302 }
5303 else if (strcmp(ptr_arg, "rstatus") == 0) {
5304 if (!*(args[cur_arg + 1])) {
5305 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5306 file, linenum, args[0], args[1], ptr_arg);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005311 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005312 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005313 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005314 free(curproxy->expect_regex);
5315 curproxy->expect_regex = NULL;
5316 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005317 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005318 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5319 error = NULL;
5320 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5321 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5322 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5323 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
5326 }
5327 }
5328 else if (strcmp(ptr_arg, "rstring") == 0) {
5329 if (!*(args[cur_arg + 1])) {
5330 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5331 file, linenum, args[0], args[1], ptr_arg);
5332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005336 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005337 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005338 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005339 free(curproxy->expect_regex);
5340 curproxy->expect_regex = NULL;
5341 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005342 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005343 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5344 error = NULL;
5345 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5346 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5347 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5348 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352 }
5353 else {
5354 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5355 file, linenum, args[0], args[1], ptr_arg);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005360 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005361 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 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005364 }
5365 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005366 else if (!strcmp(args[0], "tcp-check")) {
5367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5368 err_code |= ERR_WARN;
5369
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005370 if (strcmp(args[1], "comment") == 0) {
5371 int cur_arg;
5372 struct tcpcheck_rule *tcpcheck;
5373
5374 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005375 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005376 tcpcheck->action = TCPCHK_ACT_COMMENT;
5377
5378 if (!*args[cur_arg + 1]) {
5379 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5380 file, linenum, args[cur_arg]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384
5385 tcpcheck->comment = strdup(args[cur_arg + 1]);
5386
5387 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005388 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5389 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005390 }
5391 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005392 const char *ptr_arg;
5393 int cur_arg;
5394 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005395
5396 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005397 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5398 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5399 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5400 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5401 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005402
Willy Tarreau5581c272015-05-13 12:24:53 +02005403 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5404 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5405 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5406 file, linenum);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005409 }
5410
5411 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005412 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005413 tcpcheck->action = TCPCHK_ACT_CONNECT;
5414
5415 /* parsing each parameters to fill up the rule */
5416 while (*(ptr_arg = args[cur_arg])) {
5417 /* tcp port */
5418 if (strcmp(args[cur_arg], "port") == 0) {
5419 if ( (atol(args[cur_arg + 1]) > 65535) ||
5420 (atol(args[cur_arg + 1]) < 1) ){
5421 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5422 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
5425 }
5426 tcpcheck->port = atol(args[cur_arg + 1]);
5427 cur_arg += 2;
5428 }
5429 /* send proxy protocol */
5430 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5431 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5432 cur_arg++;
5433 }
5434#ifdef USE_OPENSSL
5435 else if (strcmp(args[cur_arg], "ssl") == 0) {
5436 curproxy->options |= PR_O_TCPCHK_SSL;
5437 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5438 cur_arg++;
5439 }
5440#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005441 /* comment for this tcpcheck line */
5442 else if (strcmp(args[cur_arg], "comment") == 0) {
5443 if (!*args[cur_arg + 1]) {
5444 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5445 file, linenum, args[cur_arg]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449 tcpcheck->comment = strdup(args[cur_arg + 1]);
5450 cur_arg += 2;
5451 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005452 else {
5453#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005454 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 +01005455#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005456 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 +01005457#endif /* USE_OPENSSL */
5458 file, linenum, args[0], args[1], args[cur_arg]);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462
5463 }
5464
5465 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5466 }
5467 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468 if (! *(args[2]) ) {
5469 /* SEND string expected */
5470 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5471 file, linenum, args[0], args[1], args[2]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 } else {
5475 struct tcpcheck_rule *tcpcheck;
5476
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005477 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478
5479 tcpcheck->action = TCPCHK_ACT_SEND;
5480 tcpcheck->string_len = strlen(args[2]);
5481 tcpcheck->string = strdup(args[2]);
5482 tcpcheck->expect_regex = NULL;
5483
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005484 /* comment for this tcpcheck line */
5485 if (strcmp(args[3], "comment") == 0) {
5486 if (!*args[4]) {
5487 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5488 file, linenum, args[3]);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 }
5492 tcpcheck->comment = strdup(args[4]);
5493 }
5494
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005495 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5496 }
5497 }
5498 else if (strcmp(args[1], "send-binary") == 0) {
5499 if (! *(args[2]) ) {
5500 /* SEND binary string expected */
5501 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5502 file, linenum, args[0], args[1], args[2]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 } else {
5506 struct tcpcheck_rule *tcpcheck;
5507 char *err = NULL;
5508
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005509 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005510
5511 tcpcheck->action = TCPCHK_ACT_SEND;
5512 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5513 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5514 file, linenum, args[0], args[1], args[2], err);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518 tcpcheck->expect_regex = NULL;
5519
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005520 /* comment for this tcpcheck line */
5521 if (strcmp(args[3], "comment") == 0) {
5522 if (!*args[4]) {
5523 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5524 file, linenum, args[3]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 tcpcheck->comment = strdup(args[4]);
5529 }
5530
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005531 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5532 }
5533 }
5534 else if (strcmp(args[1], "expect") == 0) {
5535 const char *ptr_arg;
5536 int cur_arg;
5537 int inverse = 0;
5538
5539 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5540 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
5544
5545 cur_arg = 2;
5546 /* consider exclamation marks, sole or at the beginning of a word */
5547 while (*(ptr_arg = args[cur_arg])) {
5548 while (*ptr_arg == '!') {
5549 inverse = !inverse;
5550 ptr_arg++;
5551 }
5552 if (*ptr_arg)
5553 break;
5554 cur_arg++;
5555 }
5556 /* now ptr_arg points to the beginning of a word past any possible
5557 * exclamation mark, and cur_arg is the argument which holds this word.
5558 */
5559 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005560 struct tcpcheck_rule *tcpcheck;
5561 char *err = NULL;
5562
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005563 if (!*(args[cur_arg + 1])) {
5564 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5565 file, linenum, args[0], args[1], ptr_arg);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005569
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005570 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005571
5572 tcpcheck->action = TCPCHK_ACT_EXPECT;
5573 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5574 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5575 file, linenum, args[0], args[1], args[2], err);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
5579 tcpcheck->expect_regex = NULL;
5580 tcpcheck->inverse = inverse;
5581
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005582 /* tcpcheck comment */
5583 cur_arg += 2;
5584 if (strcmp(args[cur_arg], "comment") == 0) {
5585 if (!*args[cur_arg + 1]) {
5586 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5587 file, linenum, args[cur_arg + 1]);
5588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
5590 }
5591 tcpcheck->comment = strdup(args[cur_arg + 1]);
5592 }
5593
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005594 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5595 }
5596 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005597 struct tcpcheck_rule *tcpcheck;
5598
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005599 if (!*(args[cur_arg + 1])) {
5600 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5601 file, linenum, args[0], args[1], ptr_arg);
5602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005605
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005606 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005607
5608 tcpcheck->action = TCPCHK_ACT_EXPECT;
5609 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5610 tcpcheck->string = strdup(args[cur_arg + 1]);
5611 tcpcheck->expect_regex = NULL;
5612 tcpcheck->inverse = inverse;
5613
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005614 /* tcpcheck comment */
5615 cur_arg += 2;
5616 if (strcmp(args[cur_arg], "comment") == 0) {
5617 if (!*args[cur_arg + 1]) {
5618 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5619 file, linenum, args[cur_arg + 1]);
5620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
5622 }
5623 tcpcheck->comment = strdup(args[cur_arg + 1]);
5624 }
5625
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005626 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5627 }
5628 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005629 struct tcpcheck_rule *tcpcheck;
5630
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005631 if (!*(args[cur_arg + 1])) {
5632 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5633 file, linenum, args[0], args[1], ptr_arg);
5634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005637
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005638 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005639
5640 tcpcheck->action = TCPCHK_ACT_EXPECT;
5641 tcpcheck->string_len = 0;
5642 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005643 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5644 error = NULL;
5645 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5646 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5647 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5648 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
5651 }
5652 tcpcheck->inverse = inverse;
5653
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005654 /* tcpcheck comment */
5655 cur_arg += 2;
5656 if (strcmp(args[cur_arg], "comment") == 0) {
5657 if (!*args[cur_arg + 1]) {
5658 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5659 file, linenum, args[cur_arg + 1]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663 tcpcheck->comment = strdup(args[cur_arg + 1]);
5664 }
5665
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005666 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5667 }
5668 else {
5669 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5670 file, linenum, args[0], args[1], ptr_arg);
5671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
5673 }
5674 }
5675 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005676 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
5680 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005681 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005682 if (curproxy == &defproxy) {
5683 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005686 }
5687
Willy Tarreaub80c2302007-11-30 20:51:32 +01005688 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005690
5691 if (strcmp(args[1], "fail") == 0) {
5692 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005693 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005694 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5695 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005698 }
5699
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005700 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5701 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5702 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005705 }
5706 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5707 }
5708 else {
5709 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005712 }
5713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714#ifdef TPROXY
5715 else if (!strcmp(args[0], "transparent")) {
5716 /* enable transparent proxy connections */
5717 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005718 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
5721#endif
5722 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005723 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 if (*(args[1]) == 0) {
5727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 }
5731 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005732 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005735 else if (!strcmp(args[0], "backlog")) { /* backlog */
5736 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005738
5739 if (*(args[1]) == 0) {
5740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005743 }
5744 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005745 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5746 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005747 }
Willy Tarreau86034312006-12-29 00:10:33 +01005748 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005751
Willy Tarreau86034312006-12-29 00:10:33 +01005752 if (*(args[1]) == 0) {
5753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005756 }
5757 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5759 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5762 if (*(args[1]) == 0) {
5763 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005767 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5768 if (err) {
5769 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5770 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005773 }
5774 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
5778 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005779 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005780 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005781 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005782
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 if (curproxy == &defproxy) {
5784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005788 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005789 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005790
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005791 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005792 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005793 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005794 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005795 goto out;
5796 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005797
5798 proto = protocol_by_family(sk->ss_family);
5799 if (!proto || !proto->connect) {
5800 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5801 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
5805
5806 if (port1 != port2) {
5807 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5808 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005812
5813 if (!port1) {
5814 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5815 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
5818 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005819
William Lallemanddf1425a2015-04-28 20:17:49 +02005820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5821 goto out;
5822
Willy Tarreaud5191e72010-02-09 20:50:45 +01005823 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005824 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
5826 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005828 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005829
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005830 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5831 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005836 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005837 /**
5838 * The syntax for hash-type config element is
5839 * hash-type {map-based|consistent} [[<algo>] avalanche]
5840 *
5841 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5842 */
5843 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005844
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005845 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5846 err_code |= ERR_WARN;
5847
5848 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005849 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5850 }
5851 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005852 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5853 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005854 else if (strcmp(args[1], "avalanche") == 0) {
5855 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]);
5856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005858 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005859 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005860 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
5863 }
Bhaskar98634f02013-10-29 23:30:51 -04005864
5865 /* set the hash function to use */
5866 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005867 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005868 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005869
5870 /* if consistent with no argument, then avalanche modifier is also applied */
5871 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5872 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005873 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005874 /* set the hash function */
5875 if (!strcmp(args[2], "sdbm")) {
5876 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5877 }
5878 else if (!strcmp(args[2], "djb2")) {
5879 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005880 }
5881 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005882 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005883 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005884 else if (!strcmp(args[2], "crc32")) {
5885 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5886 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005887 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005888 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 -05005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
5891 }
5892
5893 /* set the hash modifier */
5894 if (!strcmp(args[3], "avalanche")) {
5895 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5896 }
5897 else if (*args[3]) {
5898 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005902 }
William Lallemanda73203e2012-03-12 12:48:57 +01005903 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005904 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5905 if (*(args[1]) == 0) {
5906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
5910 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5911 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5912 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
5915 }
5916 }
William Lallemanda73203e2012-03-12 12:48:57 +01005917 else if (strcmp(args[0], "unique-id-format") == 0) {
5918 if (!*(args[1])) {
5919 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
5922 }
William Lallemand3203ff42012-11-11 17:30:56 +01005923 if (*(args[2])) {
5924 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5925 err_code |= ERR_ALERT | ERR_FATAL;
5926 goto out;
5927 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005928 free(curproxy->conf.uniqueid_format_string);
5929 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005930
Willy Tarreau62a61232013-04-12 18:13:46 +02005931 free(curproxy->conf.uif_file);
5932 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5933 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005934 }
William Lallemanda73203e2012-03-12 12:48:57 +01005935
5936 else if (strcmp(args[0], "unique-id-header") == 0) {
5937 if (!*(args[1])) {
5938 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5939 err_code |= ERR_ALERT | ERR_FATAL;
5940 goto out;
5941 }
5942 free(curproxy->header_unique_id);
5943 curproxy->header_unique_id = strdup(args[1]);
5944 }
5945
William Lallemand723b73a2012-02-08 16:37:49 +01005946 else if (strcmp(args[0], "log-format") == 0) {
5947 if (!*(args[1])) {
5948 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
5951 }
William Lallemand3203ff42012-11-11 17:30:56 +01005952 if (*(args[2])) {
5953 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005957 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5958 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005959
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005960 if (curproxy->conf.logformat_string == default_http_log_format)
5961 oldlogformat = "option httplog";
5962 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5963 oldlogformat = "option tcplog";
5964 else if (curproxy->conf.logformat_string == clf_http_log_format)
5965 oldlogformat = "option httplog clf";
5966 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5967 file, linenum, oldlogformat);
5968 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005969 if (curproxy->conf.logformat_string != default_http_log_format &&
5970 curproxy->conf.logformat_string != default_tcp_log_format &&
5971 curproxy->conf.logformat_string != clf_http_log_format)
5972 free(curproxy->conf.logformat_string);
5973 curproxy->conf.logformat_string = strdup(args[1]);
5974
5975 free(curproxy->conf.lfs_file);
5976 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5977 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005978
5979 /* get a chance to improve log-format error reporting by
5980 * reporting the correct line-number when possible.
5981 */
5982 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5983 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5984 file, linenum, curproxy->id);
5985 err_code |= ERR_WARN;
5986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005988 else if (!strcmp(args[0], "log-format-sd")) {
5989 if (!*(args[1])) {
5990 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5991 err_code |= ERR_ALERT | ERR_FATAL;
5992 goto out;
5993 }
5994 if (*(args[2])) {
5995 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5996 err_code |= ERR_ALERT | ERR_FATAL;
5997 goto out;
5998 }
5999
6000 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6001 free(curproxy->conf.logformat_sd_string);
6002 curproxy->conf.logformat_sd_string = strdup(args[1]);
6003
6004 free(curproxy->conf.lfsd_file);
6005 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6006 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6007
6008 /* get a chance to improve log-format-sd error reporting by
6009 * reporting the correct line-number when possible.
6010 */
6011 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6012 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6013 file, linenum, curproxy->id);
6014 err_code |= ERR_WARN;
6015 }
6016 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006017 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6018 if (*(args[1]) == 0) {
6019 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6020 err_code |= ERR_ALERT | ERR_FATAL;
6021 goto out;
6022 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006023 chunk_destroy(&curproxy->log_tag);
6024 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006025 }
William Lallemand0f99e342011-10-12 17:50:54 +02006026 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6027 /* delete previous herited or defined syslog servers */
6028 struct logsrv *back;
6029
6030 if (*(args[1]) != 0) {
6031 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
6034 }
6035
William Lallemand723b73a2012-02-08 16:37:49 +01006036 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6037 LIST_DEL(&tmplogsrv->list);
6038 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006039 }
6040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006041 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006042 struct logsrv *logsrv;
6043
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006045 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006046 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006047 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006048 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006049 LIST_INIT(&node->list);
6050 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 }
6053 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006054 struct sockaddr_storage *sk;
6055 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006056 int arg = 0;
6057 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006058
Vincent Bernat02779b62016-04-03 13:48:43 +02006059 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060
Willy Tarreau18324f52014-06-27 18:10:07 +02006061 /* just after the address, a length may be specified */
6062 if (strcmp(args[arg+2], "len") == 0) {
6063 len = atoi(args[arg+3]);
6064 if (len < 80 || len > 65535) {
6065 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6066 file, linenum, args[arg+3]);
6067 err_code |= ERR_ALERT | ERR_FATAL;
6068 goto out;
6069 }
6070 logsrv->maxlen = len;
6071
6072 /* skip these two args */
6073 arg += 2;
6074 }
6075 else
6076 logsrv->maxlen = MAX_SYSLOG_LEN;
6077
Christopher Faulet084aa962017-08-29 16:54:41 +02006078 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006079 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006080
Dragan Dosen1322d092015-09-22 16:05:32 +02006081 /* after the length, a format may be specified */
6082 if (strcmp(args[arg+2], "format") == 0) {
6083 logsrv->format = get_log_format(args[arg+3]);
6084 if (logsrv->format < 0) {
6085 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6086 err_code |= ERR_ALERT | ERR_FATAL;
6087 goto out;
6088 }
6089
6090 /* skip these two args */
6091 arg += 2;
6092 }
6093
William Lallemanddf1425a2015-04-28 20:17:49 +02006094 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6095 goto out;
6096
Willy Tarreau18324f52014-06-27 18:10:07 +02006097 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006098 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006099 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
6102
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 }
6104
William Lallemand0f99e342011-10-12 17:50:54 +02006105 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006106 if (*(args[arg+3])) {
6107 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006108 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
6112
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114 }
6115
William Lallemand0f99e342011-10-12 17:50:54 +02006116 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006117 if (*(args[arg+4])) {
6118 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006119 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006120 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
6123
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006124 }
6125 }
6126
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006127 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006128 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006129 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006130 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006131 goto out;
6132 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006133
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006134 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006136 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006137 if (port1 != port2) {
6138 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6139 file, linenum, args[0], args[1]);
6140 err_code |= ERR_ALERT | ERR_FATAL;
6141 goto out;
6142 }
6143
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006145 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146 }
William Lallemand0f99e342011-10-12 17:50:54 +02006147
6148 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 }
6150 else {
6151 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6152 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 }
6156 }
6157 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006159 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006160 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006161 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162
Willy Tarreau977b8e42006-12-29 14:19:17 +01006163 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006164 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006167 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6168 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006169 err_code |= ERR_ALERT | ERR_FATAL;
6170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006172
6173 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006174 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6175 free(curproxy->conn_src.iface_name);
6176 curproxy->conn_src.iface_name = NULL;
6177 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006178
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006179 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006180 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006181 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006182 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006183 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006184 goto out;
6185 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006186
6187 proto = protocol_by_family(sk->ss_family);
6188 if (!proto || !proto->connect) {
6189 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006190 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006191 err_code |= ERR_ALERT | ERR_FATAL;
6192 goto out;
6193 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006194
6195 if (port1 != port2) {
6196 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6197 file, linenum, args[0], args[1]);
6198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
6200 }
6201
Willy Tarreauef9a3602012-12-08 22:29:20 +01006202 curproxy->conn_src.source_addr = *sk;
6203 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006204
6205 cur_arg = 2;
6206 while (*(args[cur_arg])) {
6207 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006208#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006209 if (!*args[cur_arg + 1]) {
6210 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6211 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006212 err_code |= ERR_ALERT | ERR_FATAL;
6213 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006214 }
6215
6216 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006217 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6218 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006219 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006220 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6221 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006222 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6223 char *name, *end;
6224
6225 name = args[cur_arg+1] + 7;
6226 while (isspace(*name))
6227 name++;
6228
6229 end = name;
6230 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6231 end++;
6232
Willy Tarreauef9a3602012-12-08 22:29:20 +01006233 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6234 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6235 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6236 curproxy->conn_src.bind_hdr_len = end - name;
6237 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6238 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6239 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006240
6241 /* now look for an occurrence number */
6242 while (isspace(*end))
6243 end++;
6244 if (*end == ',') {
6245 end++;
6246 name = end;
6247 if (*end == '-')
6248 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006249 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006250 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006251 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006252 }
6253
Willy Tarreauef9a3602012-12-08 22:29:20 +01006254 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006255 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6256 " occurrences values smaller than %d.\n",
6257 file, linenum, MAX_HDR_HISTORY);
6258 err_code |= ERR_ALERT | ERR_FATAL;
6259 goto out;
6260 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006261 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006262 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006263
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006264 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006265 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006266 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006267 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006268 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006269 goto out;
6270 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006271
6272 proto = protocol_by_family(sk->ss_family);
6273 if (!proto || !proto->connect) {
6274 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6275 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006276 err_code |= ERR_ALERT | ERR_FATAL;
6277 goto out;
6278 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006280 if (port1 != port2) {
6281 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6282 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
6285 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006286 curproxy->conn_src.tproxy_addr = *sk;
6287 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006288 }
6289 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006290#else /* no TPROXY support */
6291 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006292 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006295#endif
6296 cur_arg += 2;
6297 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006298 }
6299
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6301#ifdef SO_BINDTODEVICE
6302 if (!*args[cur_arg + 1]) {
6303 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6304 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006307 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006308 free(curproxy->conn_src.iface_name);
6309 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6310 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006311 global.last_checks |= LSTCHK_NETADM;
6312#else
6313 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6314 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
6316 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006317#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006318 cur_arg += 2;
6319 continue;
6320 }
6321 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006322 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006323 err_code |= ERR_ALERT | ERR_FATAL;
6324 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006327 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6328 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6329 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006330 err_code |= ERR_ALERT | ERR_FATAL;
6331 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006334 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006337 err_code |= ERR_ALERT | ERR_FATAL;
6338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340
6341 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006342 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006343 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
6347 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006349 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006350 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 }
6354 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006356 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006357 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 }
6361 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006363 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006364 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
6368 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006370 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006371 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006375 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006377 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006378 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006380 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6385 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389
6390 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006391 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006392 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 }
6396 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006397 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006398 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006399 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 }
6403 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006404 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006405 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006406 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 }
6410 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006412 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006413 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 }
6417 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006419 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006420 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006424 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006426 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006427 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006429 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006432 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006433
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 if (curproxy == &defproxy) {
6435 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006436 err_code |= ERR_ALERT | ERR_FATAL;
6437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006439 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006440 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 if (*(args[1]) == 0) {
6443 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006444 err_code |= ERR_ALERT | ERR_FATAL;
6445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006447
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006448 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006449 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6450 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6451 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006452 err_code |= ERR_ALERT | ERR_FATAL;
6453 goto out;
6454 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006455 err_code |= warnif_cond_conflicts(cond,
6456 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6457 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006458 }
6459 else if (*args[2]) {
6460 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6461 file, linenum, args[0], args[2]);
6462 err_code |= ERR_ALERT | ERR_FATAL;
6463 goto out;
6464 }
6465
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006466 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006467 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006468 wl->s = strdup(args[1]);
6469 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006470 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 }
6472 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006473 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006476 err_code |= ERR_ALERT | ERR_FATAL;
6477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006479
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006481 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006482 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 }
6486 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006488 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006489 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 }
6493 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006495 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006496 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 }
6500 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006501 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006504 err_code |= ERR_ALERT | ERR_FATAL;
6505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 }
6507
Willy Tarreauade5ec42010-01-28 19:33:49 +01006508 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006509 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006510 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 }
6514 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006515 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006516 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006517 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
6521 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006522 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006523 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006524 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 }
6528 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006529 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006530
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531 if (curproxy == &defproxy) {
6532 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006533 err_code |= ERR_ALERT | ERR_FATAL;
6534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006536 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006537 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 if (*(args[1]) == 0) {
6540 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006541 err_code |= ERR_ALERT | ERR_FATAL;
6542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 }
6544
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006545 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006546 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6547 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6548 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006549 err_code |= ERR_ALERT | ERR_FATAL;
6550 goto out;
6551 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006552 err_code |= warnif_cond_conflicts(cond,
6553 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6554 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 }
6556 else if (*args[2]) {
6557 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6558 file, linenum, args[0], args[2]);
6559 err_code |= ERR_ALERT | ERR_FATAL;
6560 goto out;
6561 }
6562
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006563 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006564 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006565 wl->s = strdup(args[1]);
6566 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567 }
6568 else if (!strcmp(args[0], "errorloc") ||
6569 !strcmp(args[0], "errorloc302") ||
6570 !strcmp(args[0], "errorloc303")) { /* error location */
6571 int errnum, errlen;
6572 char *err;
6573
Willy Tarreau977b8e42006-12-29 14:19:17 +01006574 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006575 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006576
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006578 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006579 err_code |= ERR_ALERT | ERR_FATAL;
6580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
6582
6583 errnum = atol(args[1]);
6584 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006585 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6586 err = malloc(errlen);
6587 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006589 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6590 err = malloc(errlen);
6591 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
6593
Willy Tarreau0f772532006-12-23 20:51:41 +01006594 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6595 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006596 chunk_destroy(&curproxy->errmsg[rc]);
6597 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006598 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006601
6602 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006603 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6604 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 free(err);
6606 }
6607 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006608 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6609 int errnum, errlen, fd;
6610 char *err;
6611 struct stat stat;
6612
6613 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006614 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615
6616 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006617 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006618 err_code |= ERR_ALERT | ERR_FATAL;
6619 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006620 }
6621
6622 fd = open(args[2], O_RDONLY);
6623 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6624 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6625 file, linenum, args[2], args[1]);
6626 if (fd >= 0)
6627 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006630 }
6631
Willy Tarreau27a674e2009-08-17 07:23:33 +02006632 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006633 errlen = stat.st_size;
6634 } else {
6635 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006636 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006637 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006638 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006639 }
6640
6641 err = malloc(errlen); /* malloc() must succeed during parsing */
6642 errnum = read(fd, err, errlen);
6643 if (errnum != errlen) {
6644 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6645 file, linenum, args[2], args[1]);
6646 close(fd);
6647 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006648 err_code |= ERR_ALERT | ERR_FATAL;
6649 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006650 }
6651 close(fd);
6652
6653 errnum = atol(args[1]);
6654 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6655 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006656 chunk_destroy(&curproxy->errmsg[rc]);
6657 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006658 break;
6659 }
6660 }
6661
6662 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006663 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6664 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006665 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006666 free(err);
6667 }
6668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006669 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006670 struct cfg_kw_list *kwl;
6671 int index;
6672
6673 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6674 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6675 if (kwl->kw[index].section != CFG_LISTEN)
6676 continue;
6677 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6678 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006679 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006680 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006681 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006682 err_code |= ERR_ALERT | ERR_FATAL;
6683 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006684 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006685 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006686 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006687 err_code |= ERR_WARN;
6688 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006689 }
Willy Tarreau93893792009-07-23 13:19:11 +02006690 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006691 }
6692 }
6693 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006694
Willy Tarreau6daf3432008-01-22 16:44:08 +01006695 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006696 err_code |= ERR_ALERT | ERR_FATAL;
6697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006698 }
Willy Tarreau93893792009-07-23 13:19:11 +02006699 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006700 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006701 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702}
6703
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006704int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006705cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6706{
6707#ifdef CONFIG_HAP_NS
6708 const char *err;
6709 const char *item = args[0];
6710
6711 if (!strcmp(item, "namespace_list")) {
6712 return 0;
6713 }
6714 else if (!strcmp(item, "namespace")) {
6715 size_t idx = 1;
6716 const char *current;
6717 while (*(current = args[idx++])) {
6718 err = invalid_char(current);
6719 if (err) {
6720 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6721 file, linenum, *err, item, current);
6722 return ERR_ALERT | ERR_FATAL;
6723 }
6724
6725 if (netns_store_lookup(current, strlen(current))) {
6726 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6727 file, linenum, current);
6728 return ERR_ALERT | ERR_FATAL;
6729 }
6730 if (!netns_store_insert(current)) {
6731 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6732 file, linenum, current);
6733 return ERR_ALERT | ERR_FATAL;
6734 }
6735 }
6736 }
6737
6738 return 0;
6739#else
6740 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6741 file, linenum);
6742 return ERR_ALERT | ERR_FATAL;
6743#endif
6744}
6745
6746int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006747cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6748{
6749
6750 int err_code = 0;
6751 const char *err;
6752
6753 if (!strcmp(args[0], "userlist")) { /* new userlist */
6754 struct userlist *newul;
6755
6756 if (!*args[1]) {
6757 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6758 file, linenum, args[0]);
6759 err_code |= ERR_ALERT | ERR_FATAL;
6760 goto out;
6761 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6763 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006764
6765 err = invalid_char(args[1]);
6766 if (err) {
6767 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6768 file, linenum, *err, args[0], args[1]);
6769 err_code |= ERR_ALERT | ERR_FATAL;
6770 goto out;
6771 }
6772
6773 for (newul = userlist; newul; newul = newul->next)
6774 if (!strcmp(newul->name, args[1])) {
6775 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6776 file, linenum, args[1]);
6777 err_code |= ERR_WARN;
6778 goto out;
6779 }
6780
Vincent Bernat02779b62016-04-03 13:48:43 +02006781 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006782 if (!newul) {
6783 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6784 err_code |= ERR_ALERT | ERR_ABORT;
6785 goto out;
6786 }
6787
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006788 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006789 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006790 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6791 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006792 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006793 goto out;
6794 }
6795
6796 newul->next = userlist;
6797 userlist = newul;
6798
6799 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006800 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006801 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006802 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803
6804 if (!*args[1]) {
6805 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6806 file, linenum, args[0]);
6807 err_code |= ERR_ALERT | ERR_FATAL;
6808 goto out;
6809 }
6810
6811 err = invalid_char(args[1]);
6812 if (err) {
6813 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6814 file, linenum, *err, args[0], args[1]);
6815 err_code |= ERR_ALERT | ERR_FATAL;
6816 goto out;
6817 }
6818
William Lallemand4ac9f542015-05-28 18:03:51 +02006819 if (!userlist)
6820 goto out;
6821
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006822 for (ag = userlist->groups; ag; ag = ag->next)
6823 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006824 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6825 file, linenum, args[1], userlist->name);
6826 err_code |= ERR_ALERT;
6827 goto out;
6828 }
6829
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006830 ag = calloc(1, sizeof(*ag));
6831 if (!ag) {
6832 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6833 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 goto out;
6835 }
6836
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006837 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006838 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006839 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6840 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006841 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006842 goto out;
6843 }
6844
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006845 cur_arg = 2;
6846
6847 while (*args[cur_arg]) {
6848 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006850 cur_arg += 2;
6851 continue;
6852 } else {
6853 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6854 file, linenum, args[0]);
6855 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006856 free(ag->groupusers);
6857 free(ag->name);
6858 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006859 goto out;
6860 }
6861 }
6862
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006863 ag->next = userlist->groups;
6864 userlist->groups = ag;
6865
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866 } else if (!strcmp(args[0], "user")) { /* new user */
6867 struct auth_users *newuser;
6868 int cur_arg;
6869
6870 if (!*args[1]) {
6871 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6872 file, linenum, args[0]);
6873 err_code |= ERR_ALERT | ERR_FATAL;
6874 goto out;
6875 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006876 if (!userlist)
6877 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878
6879 for (newuser = userlist->users; newuser; newuser = newuser->next)
6880 if (!strcmp(newuser->user, args[1])) {
6881 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6882 file, linenum, args[1], userlist->name);
6883 err_code |= ERR_ALERT;
6884 goto out;
6885 }
6886
Vincent Bernat02779b62016-04-03 13:48:43 +02006887 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888 if (!newuser) {
6889 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6890 err_code |= ERR_ALERT | ERR_ABORT;
6891 goto out;
6892 }
6893
6894 newuser->user = strdup(args[1]);
6895
6896 newuser->next = userlist->users;
6897 userlist->users = newuser;
6898
6899 cur_arg = 2;
6900
6901 while (*args[cur_arg]) {
6902 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006903#ifdef CONFIG_HAP_CRYPT
6904 if (!crypt("", args[cur_arg + 1])) {
6905 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6906 file, linenum, newuser->user);
6907 err_code |= ERR_ALERT | ERR_FATAL;
6908 goto out;
6909 }
6910#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006911 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6912 file, linenum);
6913 err_code |= ERR_ALERT;
6914#endif
6915 newuser->pass = strdup(args[cur_arg + 1]);
6916 cur_arg += 2;
6917 continue;
6918 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6919 newuser->pass = strdup(args[cur_arg + 1]);
6920 newuser->flags |= AU_O_INSECURE;
6921 cur_arg += 2;
6922 continue;
6923 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006924 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006925 cur_arg += 2;
6926 continue;
6927 } else {
6928 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6929 file, linenum, args[0]);
6930 err_code |= ERR_ALERT | ERR_FATAL;
6931 goto out;
6932 }
6933 }
6934 } else {
6935 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6936 err_code |= ERR_ALERT | ERR_FATAL;
6937 }
6938
6939out:
6940 return err_code;
6941}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942
Christopher Faulet79bdef32016-11-04 22:36:15 +01006943int
6944cfg_parse_scope(const char *file, int linenum, char *line)
6945{
6946 char *beg, *end, *scope = NULL;
6947 int err_code = 0;
6948 const char *err;
6949
6950 beg = line + 1;
6951 end = strchr(beg, ']');
6952
6953 /* Detect end of scope declaration */
6954 if (!end || end == beg) {
6955 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6956 file, linenum);
6957 err_code |= ERR_ALERT | ERR_FATAL;
6958 goto out;
6959 }
6960
6961 /* Get scope name and check its validity */
6962 scope = my_strndup(beg, end-beg);
6963 err = invalid_char(scope);
6964 if (err) {
6965 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6966 file, linenum, *err);
6967 err_code |= ERR_ALERT | ERR_ABORT;
6968 goto out;
6969 }
6970
6971 /* Be sure to have a scope declaration alone on its line */
6972 line = end+1;
6973 while (isspace((unsigned char)*line))
6974 line++;
6975 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6976 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6977 file, linenum, *line);
6978 err_code |= ERR_ALERT | ERR_ABORT;
6979 goto out;
6980 }
6981
6982 /* We have a valid scope declaration, save it */
6983 free(cfg_scope);
6984 cfg_scope = scope;
6985 scope = NULL;
6986
6987 out:
6988 free(scope);
6989 return err_code;
6990}
6991
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992/*
6993 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006994 * Returns the error code, 0 if OK, or any combination of :
6995 * - ERR_ABORT: must abort ASAP
6996 * - ERR_FATAL: we can continue parsing but not start the service
6997 * - ERR_WARN: a warning has been emitted
6998 * - ERR_ALERT: an alert has been emitted
6999 * Only the two first ones can stop processing, the two others are just
7000 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007002int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003{
William Lallemand64e84512015-05-12 14:25:37 +02007004 char *thisline;
7005 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006 FILE *f;
7007 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007008 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007009 struct cfg_section *cs = NULL;
7010 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007011 int readbytes = 0;
7012
7013 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007014 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007015 return -1;
7016 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007017
David Carlier97880bb2016-04-08 10:35:26 +01007018 if ((f=fopen(file,"r")) == NULL) {
7019 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007020 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007022
William Lallemandb2f07452015-05-12 14:27:13 +02007023next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007024 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007025 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007026 char *end;
7027 char *args[MAX_LINE_ARGS + 1];
7028 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007029 int dquote = 0; /* double quote */
7030 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007031
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 linenum++;
7033
7034 end = line + strlen(line);
7035
William Lallemand64e84512015-05-12 14:25:37 +02007036 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007037 /* Check if we reached the limit and the last char is not \n.
7038 * Watch out for the last line without the terminating '\n'!
7039 */
William Lallemand64e84512015-05-12 14:25:37 +02007040 char *newline;
7041 int newlinesize = linesize * 2;
7042
7043 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7044 if (newline == NULL) {
7045 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7046 file, linenum);
7047 err_code |= ERR_ALERT | ERR_FATAL;
7048 continue;
7049 }
7050
7051 readbytes = linesize - 1;
7052 linesize = newlinesize;
7053 thisline = newline;
7054 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007055 }
7056
William Lallemand64e84512015-05-12 14:25:37 +02007057 readbytes = 0;
7058
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007060 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007062
Christopher Faulet79bdef32016-11-04 22:36:15 +01007063
7064 if (*line == '[') {/* This is the begining if a scope */
7065 err_code |= cfg_parse_scope(file, linenum, line);
7066 goto next_line;
7067 }
7068
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069 arg = 0;
7070 args[arg] = line;
7071
7072 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007073 if (*line == '"' && !squote) { /* double quote outside single quotes */
7074 if (dquote)
7075 dquote = 0;
7076 else
7077 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007078 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007079 end--;
7080 }
7081 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7082 if (squote)
7083 squote = 0;
7084 else
7085 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007086 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007087 end--;
7088 }
7089 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7091 * C equivalent value. Other combinations left unchanged (eg: \1).
7092 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 int skip = 0;
7094 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7095 *line = line[1];
7096 skip = 1;
7097 }
7098 else if (line[1] == 'r') {
7099 *line = '\r';
7100 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 else if (line[1] == 'n') {
7103 *line = '\n';
7104 skip = 1;
7105 }
7106 else if (line[1] == 't') {
7107 *line = '\t';
7108 skip = 1;
7109 }
7110 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007111 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 unsigned char hex1, hex2;
7113 hex1 = toupper(line[2]) - '0';
7114 hex2 = toupper(line[3]) - '0';
7115 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7116 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7117 *line = (hex1<<4) + hex2;
7118 skip = 3;
7119 }
7120 else {
7121 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007122 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007124 } else if (line[1] == '"') {
7125 *line = '"';
7126 skip = 1;
7127 } else if (line[1] == '\'') {
7128 *line = '\'';
7129 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007130 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7131 *line = '$';
7132 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133 }
7134 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007135 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007136 end -= skip;
7137 }
7138 line++;
7139 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007140 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007141 /* end of string, end of loop */
7142 *line = 0;
7143 break;
7144 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007145 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007147 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007148 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007149 line++;
7150 args[++arg] = line;
7151 }
William Lallemandb2f07452015-05-12 14:27:13 +02007152 else if (dquote && *line == '$') {
7153 /* environment variables are evaluated inside double quotes */
7154 char *var_beg;
7155 char *var_end;
7156 char save_char;
7157 char *value;
7158 int val_len;
7159 int newlinesize;
7160 int braces = 0;
7161
7162 var_beg = line + 1;
7163 var_end = var_beg;
7164
7165 if (*var_beg == '{') {
7166 var_beg++;
7167 var_end++;
7168 braces = 1;
7169 }
7170
7171 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7172 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7173 err_code |= ERR_ALERT | ERR_FATAL;
7174 goto next_line; /* skip current line */
7175 }
7176
7177 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7178 var_end++;
7179
7180 save_char = *var_end;
7181 *var_end = '\0';
7182 value = getenv(var_beg);
7183 *var_end = save_char;
7184 val_len = value ? strlen(value) : 0;
7185
7186 if (braces) {
7187 if (*var_end == '}') {
7188 var_end++;
7189 braces = 0;
7190 } else {
7191 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7192 err_code |= ERR_ALERT | ERR_FATAL;
7193 goto next_line; /* skip current line */
7194 }
7195 }
7196
7197 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7198
7199 /* if not enough space in thisline */
7200 if (newlinesize > linesize) {
7201 char *newline;
7202
7203 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7204 if (newline == NULL) {
7205 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7206 err_code |= ERR_ALERT | ERR_FATAL;
7207 goto next_line; /* slip current line */
7208 }
7209 /* recompute pointers if realloc returns a new pointer */
7210 if (newline != thisline) {
7211 int i;
7212 int diff;
7213
7214 for (i = 0; i <= arg; i++) {
7215 diff = args[i] - thisline;
7216 args[i] = newline + diff;
7217 }
7218
7219 diff = var_end - thisline;
7220 var_end = newline + diff;
7221 diff = end - thisline;
7222 end = newline + diff;
7223 diff = line - thisline;
7224 line = newline + diff;
7225 thisline = newline;
7226 }
7227 linesize = newlinesize;
7228 }
7229
7230 /* insert value inside the line */
7231 memmove(line + val_len, var_end, end - var_end + 1);
7232 memcpy(line, value, val_len);
7233 end += val_len - (var_end - line);
7234 line += val_len;
7235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007236 else {
7237 line++;
7238 }
7239 }
William Lallemandb2f07452015-05-12 14:27:13 +02007240
William Lallemandf9873ba2015-05-05 17:37:14 +02007241 if (dquote) {
7242 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7243 err_code |= ERR_ALERT | ERR_FATAL;
7244 }
7245
7246 if (squote) {
7247 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7248 err_code |= ERR_ALERT | ERR_FATAL;
7249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007250
7251 /* empty line */
7252 if (!**args)
7253 continue;
7254
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007255 if (*line) {
7256 /* we had to stop due to too many args.
7257 * Let's terminate the string, print the offending part then cut the
7258 * last arg.
7259 */
7260 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7261 line++;
7262 *line = '\0';
7263
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007264 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007265 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007266 err_code |= ERR_ALERT | ERR_FATAL;
7267 args[arg] = line;
7268 }
7269
Willy Tarreau540abe42007-05-02 20:50:16 +02007270 /* zero out remaining args and ensure that at least one entry
7271 * is zeroed out.
7272 */
7273 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274 args[arg] = line;
7275 }
7276
Willy Tarreau3842f002009-06-14 11:39:52 +02007277 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007278 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007279 char *tmp;
7280
Willy Tarreau3842f002009-06-14 11:39:52 +02007281 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007282 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007283 for (arg=0; *args[arg+1]; arg++)
7284 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007285 *tmp = '\0'; // fix the next arg to \0
7286 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007287 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007288 else if (!strcmp(args[0], "default")) {
7289 kwm = KWM_DEF;
7290 for (arg=0; *args[arg+1]; arg++)
7291 args[arg] = args[arg+1]; // shift args after inversion
7292 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007293
William Lallemand0f99e342011-10-12 17:50:54 +02007294 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7295 strcmp(args[0], "log") != 0) {
7296 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007297 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007298 }
7299
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007300 /* detect section start */
7301 list_for_each_entry(ics, &sections, list) {
7302 if (strcmp(args[0], ics->section_name) == 0) {
7303 cursection = ics->section_name;
7304 cs = ics;
7305 break;
7306 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007307 }
7308
Willy Tarreaubaaee002006-06-26 02:48:02 +02007309 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007310 if (cs)
7311 err_code |= cs->section_parser(file, linenum, args, kwm);
7312 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007313 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007314 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007315 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007316
7317 if (err_code & ERR_ABORT)
7318 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007319 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007320 free(cfg_scope);
7321 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007322 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007323 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007324 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007325 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007326}
7327
Willy Tarreau64ab6072014-09-16 12:17:36 +02007328/* This function propagates processes from frontend <from> to backend <to> so
7329 * that it is always guaranteed that a backend pointed to by a frontend is
7330 * bound to all of its processes. After that, if the target is a "listen"
7331 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007332 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007333 * checked first to ensure that <to> is already bound to all processes of
7334 * <from>, there is no risk of looping and we ensure to follow the shortest
7335 * path to the destination.
7336 *
7337 * It is possible to set <to> to NULL for the first call so that the function
7338 * takes care of visiting the initial frontend in <from>.
7339 *
7340 * It is important to note that the function relies on the fact that all names
7341 * have already been resolved.
7342 */
7343void propagate_processes(struct proxy *from, struct proxy *to)
7344{
7345 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007346
7347 if (to) {
7348 /* check whether we need to go down */
7349 if (from->bind_proc &&
7350 (from->bind_proc & to->bind_proc) == from->bind_proc)
7351 return;
7352
7353 if (!from->bind_proc && !to->bind_proc)
7354 return;
7355
7356 to->bind_proc = from->bind_proc ?
7357 (to->bind_proc | from->bind_proc) : 0;
7358
7359 /* now propagate down */
7360 from = to;
7361 }
7362
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007363 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007364 return;
7365
Willy Tarreauf6b70012014-12-18 14:00:43 +01007366 if (from->state == PR_STSTOPPED)
7367 return;
7368
Willy Tarreau64ab6072014-09-16 12:17:36 +02007369 /* default_backend */
7370 if (from->defbe.be)
7371 propagate_processes(from, from->defbe.be);
7372
7373 /* use_backend */
7374 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007375 if (rule->dynamic)
7376 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007377 to = rule->be.backend;
7378 propagate_processes(from, to);
7379 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007380}
7381
Willy Tarreaubb925012009-07-23 13:36:36 +02007382/*
7383 * Returns the error code, 0 if OK, or any combination of :
7384 * - ERR_ABORT: must abort ASAP
7385 * - ERR_FATAL: we can continue parsing but not start the service
7386 * - ERR_WARN: a warning has been emitted
7387 * - ERR_ALERT: an alert has been emitted
7388 * Only the two first ones can stop processing, the two others are just
7389 * indicators.
7390 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007391int check_config_validity()
7392{
7393 int cfgerr = 0;
7394 struct proxy *curproxy = NULL;
7395 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007396 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007397 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007398 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007399 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007400 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007401
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007402 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403 /*
7404 * Now, check for the integrity of all that we have collected.
7405 */
7406
7407 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007408 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007409
Willy Tarreau193b8c62012-11-22 00:17:38 +01007410 if (!global.tune.max_http_hdr)
7411 global.tune.max_http_hdr = MAX_HTTP_HDR;
7412
7413 if (!global.tune.cookie_len)
7414 global.tune.cookie_len = CAPTURE_LEN;
7415
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007416 if (!global.tune.requri_len)
7417 global.tune.requri_len = REQURI_LEN;
7418
Emeric Brun96fd9262017-07-05 13:33:16 +02007419 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7420
Willy Tarreau193b8c62012-11-22 00:17:38 +01007421 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7422
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007423 /* allocate pool of resolution per resolvers */
7424 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7425 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7426 /* error message is already displayed by dns_alloc_resolution_pool() */
7427 err_code |= ERR_ALERT | ERR_ABORT;
7428 goto out;
7429 }
7430 }
7431
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007432 /* Post initialisation of the users and groups lists. */
7433 err_code = userlist_postinit();
7434 if (err_code != ERR_NONE)
7435 goto out;
7436
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007437 /* first, we will invert the proxy list order */
7438 curproxy = NULL;
7439 while (proxy) {
7440 struct proxy *next;
7441
7442 next = proxy->next;
7443 proxy->next = curproxy;
7444 curproxy = proxy;
7445 if (!next)
7446 break;
7447 proxy = next;
7448 }
7449
Willy Tarreau419ead82014-09-16 13:41:21 +02007450 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007451 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007452 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007453 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007454 struct act_rule *trule;
7455 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007456 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007457 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007458 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007459
Willy Tarreau050536d2012-10-04 08:47:34 +02007460 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007461 /* proxy ID not set, use automatic numbering with first
7462 * spare entry starting with next_pxid.
7463 */
7464 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7465 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7466 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007467 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007468 next_pxid++;
7469
Willy Tarreau55ea7572007-06-17 19:56:27 +02007470
Willy Tarreaubaaee002006-06-26 02:48:02 +02007471 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007472 /* ensure we don't keep listeners uselessly bound */
7473 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007474 free((void *)curproxy->table.peers.name);
7475 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007476 continue;
7477 }
7478
Willy Tarreau102df612014-05-07 23:56:38 +02007479 /* Check multi-process mode compatibility for the current proxy */
7480
7481 if (curproxy->bind_proc) {
7482 /* an explicit bind-process was specified, let's check how many
7483 * processes remain.
7484 */
David Carliere6c39412015-07-02 07:00:17 +00007485 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007486
7487 curproxy->bind_proc &= nbits(global.nbproc);
7488 if (!curproxy->bind_proc && nbproc == 1) {
7489 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);
7490 curproxy->bind_proc = 1;
7491 }
7492 else if (!curproxy->bind_proc && nbproc > 1) {
7493 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);
7494 curproxy->bind_proc = 0;
7495 }
7496 }
7497
Willy Tarreau3d209582014-05-09 17:06:11 +02007498 /* check and reduce the bind-proc of each listener */
7499 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7500 unsigned long mask;
7501
7502 if (!bind_conf->bind_proc)
7503 continue;
7504
7505 mask = nbits(global.nbproc);
7506 if (curproxy->bind_proc)
7507 mask &= curproxy->bind_proc;
7508 /* mask cannot be null here thanks to the previous checks */
7509
David Carliere6c39412015-07-02 07:00:17 +00007510 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007511 bind_conf->bind_proc &= mask;
7512
7513 if (!bind_conf->bind_proc && nbproc == 1) {
7514 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",
7515 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7516 bind_conf->bind_proc = mask & ~(mask - 1);
7517 }
7518 else if (!bind_conf->bind_proc && nbproc > 1) {
7519 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",
7520 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7521 bind_conf->bind_proc = 0;
7522 }
7523 }
7524
Willy Tarreauff01a212009-03-15 13:46:16 +01007525 switch (curproxy->mode) {
7526 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007527 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007528 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007529 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7530 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007531 cfgerr++;
7532 }
7533
7534 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007535 Warning("config : servers will be ignored for %s '%s'.\n",
7536 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007537 break;
7538
7539 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007540 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007541 break;
7542
7543 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007544 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007545 break;
7546 }
7547
Willy Tarreauf3934b82015-08-11 11:36:45 +02007548 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7549 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7550 proxy_type_str(curproxy), curproxy->id);
7551 err_code |= ERR_WARN;
7552 }
7553
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007554 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007555 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007556 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007557 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007559 cfgerr++;
7560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007561#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007562 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007563 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007565 cfgerr++;
7566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007567#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007568 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007569 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007571 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 }
7573 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007574 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007575 /* If no LB algo is set in a backend, and we're not in
7576 * transparent mode, dispatch mode nor proxy mode, we
7577 * want to use balance roundrobin by default.
7578 */
7579 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7580 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007581 }
7582 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007583
Willy Tarreau1620ec32011-08-06 17:05:02 +02007584 if (curproxy->options & PR_O_DISPATCH)
7585 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7586 else if (curproxy->options & PR_O_HTTP_PROXY)
7587 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7588 else if (curproxy->options & PR_O_TRANSP)
7589 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007590
Willy Tarreau1620ec32011-08-06 17:05:02 +02007591 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7592 if (curproxy->options & PR_O_DISABLE404) {
7593 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7594 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7595 err_code |= ERR_WARN;
7596 curproxy->options &= ~PR_O_DISABLE404;
7597 }
7598 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7599 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7600 "send-state", proxy_type_str(curproxy), curproxy->id);
7601 err_code |= ERR_WARN;
7602 curproxy->options &= ~PR_O2_CHK_SNDST;
7603 }
Willy Tarreauef781042010-01-27 11:53:01 +01007604 }
7605
Simon Horman98637e52014-06-20 12:30:16 +09007606 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7607 if (!global.external_check) {
7608 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7609 curproxy->id, "option external-check");
7610 cfgerr++;
7611 }
7612 if (!curproxy->check_command) {
7613 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7614 curproxy->id, "option external-check");
7615 cfgerr++;
7616 }
7617 }
7618
Simon Horman64e34162015-02-06 11:11:57 +09007619 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007620 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7621 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007622 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7623 "'email-alert myhostname', or 'email-alert to' "
7624 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007625 "to be present).\n",
7626 proxy_type_str(curproxy), curproxy->id);
7627 err_code |= ERR_WARN;
7628 free_email_alert(curproxy);
7629 }
7630 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007631 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007632 }
7633
Simon Horman98637e52014-06-20 12:30:16 +09007634 if (curproxy->check_command) {
7635 int clear = 0;
7636 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7637 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7638 "external-check command", proxy_type_str(curproxy), curproxy->id);
7639 err_code |= ERR_WARN;
7640 clear = 1;
7641 }
7642 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007643 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007644 curproxy->id, "external-check command");
7645 cfgerr++;
7646 }
7647 if (clear) {
7648 free(curproxy->check_command);
7649 curproxy->check_command = NULL;
7650 }
7651 }
7652
7653 if (curproxy->check_path) {
7654 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7655 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7656 "external-check path", proxy_type_str(curproxy), curproxy->id);
7657 err_code |= ERR_WARN;
7658 free(curproxy->check_path);
7659 curproxy->check_path = NULL;
7660 }
7661 }
7662
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007663 /* if a default backend was specified, let's find it */
7664 if (curproxy->defbe.name) {
7665 struct proxy *target;
7666
Willy Tarreauafb39922015-05-26 12:04:09 +02007667 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007668 if (!target) {
7669 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7670 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007671 cfgerr++;
7672 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007673 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7674 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007675 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007676 } else if (target->mode != curproxy->mode &&
7677 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7678
7679 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7680 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7681 curproxy->conf.file, curproxy->conf.line,
7682 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7683 target->conf.file, target->conf.line);
7684 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007685 } else {
7686 free(curproxy->defbe.name);
7687 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007688 /* Update tot_fe_maxconn for a further fullconn's computation */
7689 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007690 /* Emit a warning if this proxy also has some servers */
7691 if (curproxy->srv) {
7692 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7693 curproxy->id);
7694 err_code |= ERR_WARN;
7695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007696 }
7697 }
7698
Emeric Brun3f783572017-01-12 11:21:28 +01007699 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7700 /* Case of listen without default backend
7701 * The curproxy will be its own default backend
7702 * so we update tot_fe_maxconn for a further
7703 * fullconn's computation */
7704 curproxy->tot_fe_maxconn += curproxy->maxconn;
7705 }
7706
Willy Tarreau55ea7572007-06-17 19:56:27 +02007707 /* find the target proxy for 'use_backend' rules */
7708 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007709 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007710 struct logformat_node *node;
7711 char *pxname;
7712
7713 /* Try to parse the string as a log format expression. If the result
7714 * of the parsing is only one entry containing a simple string, then
7715 * it's a standard string corresponding to a static rule, thus the
7716 * parsing is cancelled and be.name is restored to be resolved.
7717 */
7718 pxname = rule->be.name;
7719 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007720 curproxy->conf.args.ctx = ARGC_UBK;
7721 curproxy->conf.args.file = rule->file;
7722 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007723 err = NULL;
7724 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7725 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7726 rule->file, rule->line, pxname, err);
7727 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007728 cfgerr++;
7729 continue;
7730 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007731 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7732
7733 if (!LIST_ISEMPTY(&rule->be.expr)) {
7734 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7735 rule->dynamic = 1;
7736 free(pxname);
7737 continue;
7738 }
7739 /* simple string: free the expression and fall back to static rule */
7740 free(node->arg);
7741 free(node);
7742 }
7743
7744 rule->dynamic = 0;
7745 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007746
Willy Tarreauafb39922015-05-26 12:04:09 +02007747 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007748 if (!target) {
7749 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7750 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007751 cfgerr++;
7752 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007753 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7754 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007755 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007756 } else if (target->mode != curproxy->mode &&
7757 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7758
7759 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7760 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7761 curproxy->conf.file, curproxy->conf.line,
7762 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7763 target->conf.file, target->conf.line);
7764 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007765 } else {
7766 free((void *)rule->be.name);
7767 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007768 /* For each target of switching rules, we update
7769 * their tot_fe_maxconn, except if a previous rule point
7770 * on the same backend or on the default backend */
7771 if (rule->be.backend != curproxy->defbe.be) {
7772 struct switching_rule *swrule;
7773
7774 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7775 if (rule == swrule) {
7776 target->tot_fe_maxconn += curproxy->maxconn;
7777 break;
7778 }
7779 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7780 /* there is multiple ref of this backend */
7781 break;
7782 }
7783 }
7784 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007785 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007786 }
7787
Willy Tarreau64ab6072014-09-16 12:17:36 +02007788 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007789 list_for_each_entry(srule, &curproxy->server_rules, list) {
7790 struct server *target = findserver(curproxy, srule->srv.name);
7791
7792 if (!target) {
7793 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7794 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7795 cfgerr++;
7796 continue;
7797 }
7798 free((void *)srule->srv.name);
7799 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007800 }
7801
Emeric Brunb982a3d2010-01-04 15:45:53 +01007802 /* find the target table for 'stick' rules */
7803 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7804 struct proxy *target;
7805
Emeric Brun1d33b292010-01-04 15:47:17 +01007806 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7807 if (mrule->flags & STK_IS_STORE)
7808 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7809
Emeric Brunb982a3d2010-01-04 15:45:53 +01007810 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007811 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007812 else
7813 target = curproxy;
7814
7815 if (!target) {
7816 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7817 curproxy->id, mrule->table.name);
7818 cfgerr++;
7819 }
7820 else if (target->table.size == 0) {
7821 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7822 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7823 cfgerr++;
7824 }
Willy Tarreau12785782012-04-27 21:37:17 +02007825 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7826 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007827 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7828 cfgerr++;
7829 }
7830 else {
7831 free((void *)mrule->table.name);
7832 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007833 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007834 }
7835 }
7836
7837 /* find the target table for 'store response' rules */
7838 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7839 struct proxy *target;
7840
Emeric Brun1d33b292010-01-04 15:47:17 +01007841 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7842
Emeric Brunb982a3d2010-01-04 15:45:53 +01007843 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007844 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007845 else
7846 target = curproxy;
7847
7848 if (!target) {
7849 Alert("Proxy '%s': unable to find store table '%s'.\n",
7850 curproxy->id, mrule->table.name);
7851 cfgerr++;
7852 }
7853 else if (target->table.size == 0) {
7854 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7855 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7856 cfgerr++;
7857 }
Willy Tarreau12785782012-04-27 21:37:17 +02007858 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7859 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007860 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7861 cfgerr++;
7862 }
7863 else {
7864 free((void *)mrule->table.name);
7865 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007866 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007867 }
7868 }
7869
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007870 /* find the target table for 'tcp-request' layer 4 rules */
7871 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7872 struct proxy *target;
7873
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007874 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007875 continue;
7876
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007877 if (trule->arg.trk_ctr.table.n)
7878 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007879 else
7880 target = curproxy;
7881
7882 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007883 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007884 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007885 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007886 cfgerr++;
7887 }
7888 else if (target->table.size == 0) {
7889 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007891 cfgerr++;
7892 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007893 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007894 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007895 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007896 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007897 cfgerr++;
7898 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007899 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 free(trule->arg.trk_ctr.table.n);
7901 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007902 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007903 * to pass a list of counters to track and allocate them right here using
7904 * stktable_alloc_data_type().
7905 */
7906 }
7907 }
7908
Willy Tarreau620408f2016-10-21 16:37:51 +02007909 /* find the target table for 'tcp-request' layer 5 rules */
7910 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7911 struct proxy *target;
7912
7913 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7914 continue;
7915
7916 if (trule->arg.trk_ctr.table.n)
7917 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7918 else
7919 target = curproxy;
7920
7921 if (!target) {
7922 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7923 curproxy->id, trule->arg.trk_ctr.table.n,
7924 tcp_trk_idx(trule->action));
7925 cfgerr++;
7926 }
7927 else if (target->table.size == 0) {
7928 Alert("Proxy '%s': table '%s' used but not configured.\n",
7929 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7930 cfgerr++;
7931 }
7932 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7933 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7934 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7935 tcp_trk_idx(trule->action));
7936 cfgerr++;
7937 }
7938 else {
7939 free(trule->arg.trk_ctr.table.n);
7940 trule->arg.trk_ctr.table.t = &target->table;
7941 /* Note: if we decide to enhance the track-sc syntax, we may be able
7942 * to pass a list of counters to track and allocate them right here using
7943 * stktable_alloc_data_type().
7944 */
7945 }
7946 }
7947
Willy Tarreaud1f96522010-08-03 19:34:32 +02007948 /* find the target table for 'tcp-request' layer 6 rules */
7949 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7950 struct proxy *target;
7951
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007952 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007953 continue;
7954
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007955 if (trule->arg.trk_ctr.table.n)
7956 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007957 else
7958 target = curproxy;
7959
7960 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007961 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007962 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007963 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007964 cfgerr++;
7965 }
7966 else if (target->table.size == 0) {
7967 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007968 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007969 cfgerr++;
7970 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007971 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007972 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007973 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007974 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007975 cfgerr++;
7976 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007977 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007978 free(trule->arg.trk_ctr.table.n);
7979 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007980 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007981 * to pass a list of counters to track and allocate them right here using
7982 * stktable_alloc_data_type().
7983 */
7984 }
7985 }
7986
Baptiste Assmanne9544932015-11-03 23:31:35 +01007987 /* parse http-request capture rules to ensure id really exists */
7988 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7989 if (hrqrule->action != ACT_CUSTOM ||
7990 hrqrule->action_ptr != http_action_req_capture_by_id)
7991 continue;
7992
7993 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7994 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7995 curproxy->id, hrqrule->arg.capid.idx);
7996 cfgerr++;
7997 }
7998 }
7999
8000 /* parse http-response capture rules to ensure id really exists */
8001 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8002 if (hrqrule->action != ACT_CUSTOM ||
8003 hrqrule->action_ptr != http_action_res_capture_by_id)
8004 continue;
8005
8006 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8007 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8008 curproxy->id, hrqrule->arg.capid.idx);
8009 cfgerr++;
8010 }
8011 }
8012
Willy Tarreau09448f72014-06-25 18:12:15 +02008013 /* find the target table for 'http-request' layer 7 rules */
8014 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8015 struct proxy *target;
8016
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008017 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008018 continue;
8019
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008020 if (hrqrule->arg.trk_ctr.table.n)
8021 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008022 else
8023 target = curproxy;
8024
8025 if (!target) {
8026 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008027 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008028 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008029 cfgerr++;
8030 }
8031 else if (target->table.size == 0) {
8032 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008033 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008034 cfgerr++;
8035 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008036 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008037 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008038 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008039 http_trk_idx(hrqrule->action));
8040 cfgerr++;
8041 }
8042 else {
8043 free(hrqrule->arg.trk_ctr.table.n);
8044 hrqrule->arg.trk_ctr.table.t = &target->table;
8045 /* Note: if we decide to enhance the track-sc syntax, we may be able
8046 * to pass a list of counters to track and allocate them right here using
8047 * stktable_alloc_data_type().
8048 */
8049 }
8050 }
8051
8052 /* find the target table for 'http-response' layer 7 rules */
8053 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8054 struct proxy *target;
8055
8056 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8057 continue;
8058
8059 if (hrqrule->arg.trk_ctr.table.n)
8060 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8061 else
8062 target = curproxy;
8063
8064 if (!target) {
8065 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8066 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8067 http_trk_idx(hrqrule->action));
8068 cfgerr++;
8069 }
8070 else if (target->table.size == 0) {
8071 Alert("Proxy '%s': table '%s' used but not configured.\n",
8072 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8073 cfgerr++;
8074 }
8075 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8076 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8077 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8078 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008079 cfgerr++;
8080 }
8081 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008082 free(hrqrule->arg.trk_ctr.table.n);
8083 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008084 /* Note: if we decide to enhance the track-sc syntax, we may be able
8085 * to pass a list of counters to track and allocate them right here using
8086 * stktable_alloc_data_type().
8087 */
8088 }
8089 }
8090
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008091 /* move any "block" rules at the beginning of the http-request rules */
8092 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8093 /* insert block_rules into http_req_rules at the beginning */
8094 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8095 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8096 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8097 curproxy->http_req_rules.n = curproxy->block_rules.n;
8098 LIST_INIT(&curproxy->block_rules);
8099 }
8100
Emeric Brun32da3c42010-09-23 18:39:19 +02008101 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008102 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008103
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008104 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008105 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8106 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008107 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008108 break;
8109 }
8110 }
8111
8112 if (!curpeers) {
8113 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8114 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008115 free((void *)curproxy->table.peers.name);
8116 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008117 cfgerr++;
8118 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008119 else if (curpeers->state == PR_STSTOPPED) {
8120 /* silently disable this peers section */
8121 curproxy->table.peers.p = NULL;
8122 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008123 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008124 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8125 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008126 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008127 cfgerr++;
8128 }
8129 }
8130
Simon Horman9dc49962015-01-30 11:22:59 +09008131
8132 if (curproxy->email_alert.mailers.name) {
8133 struct mailers *curmailers = mailers;
8134
8135 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8136 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8137 free(curproxy->email_alert.mailers.name);
8138 curproxy->email_alert.mailers.m = curmailers;
8139 curmailers->users++;
8140 break;
8141 }
8142 }
8143
8144 if (!curmailers) {
8145 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8146 curproxy->id, curproxy->email_alert.mailers.name);
8147 free_email_alert(curproxy);
8148 cfgerr++;
8149 }
8150 }
8151
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008152 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008153 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008154 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8155 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8156 "proxy", curproxy->id);
8157 cfgerr++;
8158 goto out_uri_auth_compat;
8159 }
8160
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008161 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008162 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008163 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008164 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008165
Willy Tarreau95fa4692010-02-01 13:05:50 +01008166 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8167 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008168
8169 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008170 uri_auth_compat_req[i++] = "realm";
8171 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8172 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008173
Willy Tarreau95fa4692010-02-01 13:05:50 +01008174 uri_auth_compat_req[i++] = "unless";
8175 uri_auth_compat_req[i++] = "{";
8176 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8177 uri_auth_compat_req[i++] = "}";
8178 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008179
Willy Tarreauff011f22011-01-06 17:51:27 +01008180 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8181 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008182 cfgerr++;
8183 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008184 }
8185
Willy Tarreauff011f22011-01-06 17:51:27 +01008186 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008187
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008188 if (curproxy->uri_auth->auth_realm) {
8189 free(curproxy->uri_auth->auth_realm);
8190 curproxy->uri_auth->auth_realm = NULL;
8191 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008192
8193 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008194 }
8195out_uri_auth_compat:
8196
Dragan Dosen43885c72015-10-01 13:18:13 +02008197 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008198 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008199 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8200 if (!curproxy->conf.logformat_sd_string) {
8201 /* set the default logformat_sd_string */
8202 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8203 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008204 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008205 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008206 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008207
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008208 /* compile the log format */
8209 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008210 if (curproxy->conf.logformat_string != default_http_log_format &&
8211 curproxy->conf.logformat_string != default_tcp_log_format &&
8212 curproxy->conf.logformat_string != clf_http_log_format)
8213 free(curproxy->conf.logformat_string);
8214 curproxy->conf.logformat_string = NULL;
8215 free(curproxy->conf.lfs_file);
8216 curproxy->conf.lfs_file = NULL;
8217 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008218
8219 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8220 free(curproxy->conf.logformat_sd_string);
8221 curproxy->conf.logformat_sd_string = NULL;
8222 free(curproxy->conf.lfsd_file);
8223 curproxy->conf.lfsd_file = NULL;
8224 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008225 }
8226
Willy Tarreau62a61232013-04-12 18:13:46 +02008227 if (curproxy->conf.logformat_string) {
8228 curproxy->conf.args.ctx = ARGC_LOG;
8229 curproxy->conf.args.file = curproxy->conf.lfs_file;
8230 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008231 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008232 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008233 SMP_VAL_FE_LOG_END, &err)) {
8234 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8235 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8236 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008237 cfgerr++;
8238 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008239 curproxy->conf.args.file = NULL;
8240 curproxy->conf.args.line = 0;
8241 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008242
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008243 if (curproxy->conf.logformat_sd_string) {
8244 curproxy->conf.args.ctx = ARGC_LOGSD;
8245 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8246 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008247 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008248 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 +01008249 SMP_VAL_FE_LOG_END, &err)) {
8250 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8251 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8252 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008253 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008254 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8255 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8256 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8257 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008258 cfgerr++;
8259 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008260 curproxy->conf.args.file = NULL;
8261 curproxy->conf.args.line = 0;
8262 }
8263
Willy Tarreau62a61232013-04-12 18:13:46 +02008264 if (curproxy->conf.uniqueid_format_string) {
8265 curproxy->conf.args.ctx = ARGC_UIF;
8266 curproxy->conf.args.file = curproxy->conf.uif_file;
8267 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008268 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008269 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 +01008270 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8271 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8272 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8273 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008274 cfgerr++;
8275 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008276 curproxy->conf.args.file = NULL;
8277 curproxy->conf.args.line = 0;
8278 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008279
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008280 /* only now we can check if some args remain unresolved.
8281 * This must be done after the users and groups resolution.
8282 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008283 cfgerr += smp_resolve_args(curproxy);
8284 if (!cfgerr)
8285 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008286
Willy Tarreau2738a142006-07-08 17:28:09 +02008287 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008288 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008289 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008290 (!curproxy->timeout.connect ||
8291 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008292 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008293 " | While not properly invalid, you will certainly encounter various problems\n"
8294 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008295 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008296 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008297 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008298 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008299
Willy Tarreau1fa31262007-12-03 00:36:16 +01008300 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8301 * We must still support older configurations, so let's find out whether those
8302 * parameters have been set or must be copied from contimeouts.
8303 */
8304 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008305 if (!curproxy->timeout.tarpit ||
8306 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008307 /* tarpit timeout not set. We search in the following order:
8308 * default.tarpit, curr.connect, default.connect.
8309 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008310 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008311 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008312 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008313 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008314 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008315 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008316 }
8317 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008318 (!curproxy->timeout.queue ||
8319 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008320 /* queue timeout not set. We search in the following order:
8321 * default.queue, curr.connect, default.connect.
8322 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008323 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008324 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008325 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008326 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008327 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008328 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008329 }
8330 }
8331
Willy Tarreau1620ec32011-08-06 17:05:02 +02008332 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008333 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008334 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008335 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008336 }
8337
Willy Tarreau215663d2014-06-13 18:30:23 +02008338 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8339 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8340 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8341 proxy_type_str(curproxy), curproxy->id);
8342 err_code |= ERR_WARN;
8343 }
8344
Willy Tarreau193b8c62012-11-22 00:17:38 +01008345 /* ensure that cookie capture length is not too large */
8346 if (curproxy->capture_len >= global.tune.cookie_len) {
8347 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8348 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8349 err_code |= ERR_WARN;
8350 curproxy->capture_len = global.tune.cookie_len - 1;
8351 }
8352
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008353 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008354 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008355 curproxy->req_cap_pool = create_pool("ptrcap",
8356 curproxy->nb_req_cap * sizeof(char *),
8357 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008358 }
8359
8360 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008361 curproxy->rsp_cap_pool = create_pool("ptrcap",
8362 curproxy->nb_rsp_cap * sizeof(char *),
8363 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008364 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008365
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008366 switch (curproxy->load_server_state_from_file) {
8367 case PR_SRV_STATE_FILE_UNSPEC:
8368 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8369 break;
8370 case PR_SRV_STATE_FILE_GLOBAL:
8371 if (!global.server_state_file) {
8372 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",
8373 curproxy->id);
8374 err_code |= ERR_WARN;
8375 }
8376 break;
8377 }
8378
Willy Tarreaubaaee002006-06-26 02:48:02 +02008379 /* first, we will invert the servers list order */
8380 newsrv = NULL;
8381 while (curproxy->srv) {
8382 struct server *next;
8383
8384 next = curproxy->srv->next;
8385 curproxy->srv->next = newsrv;
8386 newsrv = curproxy->srv;
8387 if (!next)
8388 break;
8389 curproxy->srv = next;
8390 }
8391
Willy Tarreau17edc812014-01-03 12:14:34 +01008392 /* Check that no server name conflicts. This causes trouble in the stats.
8393 * We only emit a warning for the first conflict affecting each server,
8394 * in order to avoid combinatory explosion if all servers have the same
8395 * name. We do that only for servers which do not have an explicit ID,
8396 * because these IDs were made also for distinguishing them and we don't
8397 * want to annoy people who correctly manage them.
8398 */
8399 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8400 struct server *other_srv;
8401
8402 if (newsrv->puid)
8403 continue;
8404
8405 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8406 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8407 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8408 newsrv->conf.file, newsrv->conf.line,
8409 proxy_type_str(curproxy), curproxy->id,
8410 newsrv->id, other_srv->conf.line);
8411 break;
8412 }
8413 }
8414 }
8415
Willy Tarreaudd701652010-05-25 23:03:02 +02008416 /* assign automatic UIDs to servers which don't have one yet */
8417 next_id = 1;
8418 newsrv = curproxy->srv;
8419 while (newsrv != NULL) {
8420 if (!newsrv->puid) {
8421 /* server ID not set, use automatic numbering with first
8422 * spare entry starting with next_svid.
8423 */
8424 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8425 newsrv->conf.id.key = newsrv->puid = next_id;
8426 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8427 }
8428 next_id++;
8429 newsrv = newsrv->next;
8430 }
8431
Willy Tarreau20697042007-11-15 23:26:18 +01008432 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008433 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008434
Willy Tarreau62c3be22012-01-20 13:12:32 +01008435 /*
8436 * If this server supports a maxconn parameter, it needs a dedicated
8437 * tasks to fill the emptied slots when a connection leaves.
8438 * Also, resolve deferred tracking dependency if needed.
8439 */
8440 newsrv = curproxy->srv;
8441 while (newsrv != NULL) {
8442 if (newsrv->minconn > newsrv->maxconn) {
8443 /* Only 'minconn' was specified, or it was higher than or equal
8444 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8445 * this will avoid further useless expensive computations.
8446 */
8447 newsrv->maxconn = newsrv->minconn;
8448 } else if (newsrv->maxconn && !newsrv->minconn) {
8449 /* minconn was not specified, so we set it to maxconn */
8450 newsrv->minconn = newsrv->maxconn;
8451 }
8452
Willy Tarreau17d45382016-12-22 21:16:08 +01008453 /* this will also properly set the transport layer for prod and checks */
8454 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8455 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8456 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8457 }
Emeric Brun94324a42012-10-11 14:00:19 +02008458
Willy Tarreau2f075e92013-12-03 11:11:34 +01008459 /* set the check type on the server */
8460 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8461
Willy Tarreau62c3be22012-01-20 13:12:32 +01008462 if (newsrv->trackit) {
8463 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008464 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008465 char *pname, *sname;
8466
8467 pname = newsrv->trackit;
8468 sname = strrchr(pname, '/');
8469
8470 if (sname)
8471 *sname++ = '\0';
8472 else {
8473 sname = pname;
8474 pname = NULL;
8475 }
8476
8477 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008478 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008479 if (!px) {
8480 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8481 proxy_type_str(curproxy), curproxy->id,
8482 newsrv->id, pname);
8483 cfgerr++;
8484 goto next_srv;
8485 }
8486 } else
8487 px = curproxy;
8488
8489 srv = findserver(px, sname);
8490 if (!srv) {
8491 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8492 proxy_type_str(curproxy), curproxy->id,
8493 newsrv->id, sname);
8494 cfgerr++;
8495 goto next_srv;
8496 }
8497
Willy Tarreau32091232014-05-16 13:52:00 +02008498 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8499 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8500 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008501 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008502 "tracking as it does not have any check nor agent enabled.\n",
8503 proxy_type_str(curproxy), curproxy->id,
8504 newsrv->id, px->id, srv->id);
8505 cfgerr++;
8506 goto next_srv;
8507 }
8508
8509 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8510
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008511 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008512 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8513 "belongs to a tracking chain looping back to %s/%s.\n",
8514 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008515 newsrv->id, px->id, srv->id, px->id,
8516 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008517 cfgerr++;
8518 goto next_srv;
8519 }
8520
8521 if (curproxy != px &&
8522 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8523 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8524 "tracking: disable-on-404 option inconsistency.\n",
8525 proxy_type_str(curproxy), curproxy->id,
8526 newsrv->id, px->id, srv->id);
8527 cfgerr++;
8528 goto next_srv;
8529 }
8530
Willy Tarreau62c3be22012-01-20 13:12:32 +01008531 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008532 newsrv->tracknext = srv->trackers;
8533 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008534
8535 free(newsrv->trackit);
8536 newsrv->trackit = NULL;
8537 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008538
8539 /*
8540 * resolve server's resolvers name and update the resolvers pointer
8541 * accordingly
8542 */
8543 if (newsrv->resolvers_id) {
8544 struct dns_resolvers *curr_resolvers;
8545 int found;
8546
8547 found = 0;
8548 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8549 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8550 found = 1;
8551 break;
8552 }
8553 }
8554
8555 if (!found) {
8556 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8557 proxy_type_str(curproxy), curproxy->id,
8558 newsrv->id, newsrv->resolvers_id);
8559 cfgerr++;
8560 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008561 if (newsrv->srvrq) {
8562 if (!newsrv->srvrq->resolvers) {
8563 newsrv->srvrq->resolvers = curr_resolvers;
8564 if (dns_link_resolution(newsrv->srvrq,
8565 OBJ_TYPE_SRVRQ, NULL) != 0) {
8566 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8567 proxy_type_str(curproxy), curproxy->id,
8568 newsrv->id);
8569 cfgerr++;
8570 }
8571 }
8572
8573 }
8574 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008575 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008576 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8577 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8578 proxy_type_str(curproxy), curproxy->id,
8579 newsrv->id);
8580 cfgerr++;
8581 }
8582 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008583 }
8584 }
8585 else {
8586 /* if no resolvers section associated to this server
8587 * we can clean up the associated resolution structure
8588 */
8589 if (newsrv->resolution) {
8590 free(newsrv->resolution->hostname_dn);
8591 newsrv->resolution->hostname_dn = NULL;
8592 free(newsrv->resolution);
8593 newsrv->resolution = NULL;
8594 }
8595 }
8596
Willy Tarreau62c3be22012-01-20 13:12:32 +01008597 next_srv:
8598 newsrv = newsrv->next;
8599 }
8600
Olivier Houchard4e694042017-03-14 20:01:29 +01008601 /*
8602 * Try to generate dynamic cookies for servers now.
8603 * It couldn't be done earlier, since at the time we parsed
8604 * the server line, we may not have known yet that we
8605 * should use dynamic cookies, or the secret key may not
8606 * have been provided yet.
8607 */
8608 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8609 newsrv = curproxy->srv;
8610 while (newsrv != NULL) {
8611 srv_set_dyncookie(newsrv);
8612 newsrv = newsrv->next;
8613 }
8614
8615 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008616 /* We have to initialize the server lookup mechanism depending
8617 * on what LB algorithm was choosen.
8618 */
8619
8620 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8621 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8622 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008623 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8624 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8625 init_server_map(curproxy);
8626 } else {
8627 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8628 fwrr_init_server_groups(curproxy);
8629 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008630 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008631
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008632 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008633 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8634 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8635 fwlc_init_server_tree(curproxy);
8636 } else {
8637 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8638 fas_init_server_tree(curproxy);
8639 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008640 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008641
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008642 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008643 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8644 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8645 chash_init_server_tree(curproxy);
8646 } else {
8647 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8648 init_server_map(curproxy);
8649 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008650 break;
8651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008652
8653 if (curproxy->options & PR_O_LOGASAP)
8654 curproxy->to_log &= ~LW_BYTES;
8655
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008656 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008657 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8658 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008659 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8660 proxy_type_str(curproxy), curproxy->id);
8661 err_code |= ERR_WARN;
8662 }
8663
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008664 if (curproxy->mode != PR_MODE_HTTP) {
8665 int optnum;
8666
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008667 if (curproxy->uri_auth) {
8668 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8669 proxy_type_str(curproxy), curproxy->id);
8670 err_code |= ERR_WARN;
8671 curproxy->uri_auth = NULL;
8672 }
8673
Willy Tarreaude7dc882017-03-10 11:49:21 +01008674 if (curproxy->capture_name) {
8675 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8676 proxy_type_str(curproxy), curproxy->id);
8677 err_code |= ERR_WARN;
8678 }
8679
8680 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8681 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8682 proxy_type_str(curproxy), curproxy->id);
8683 err_code |= ERR_WARN;
8684 }
8685
8686 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8687 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8688 proxy_type_str(curproxy), curproxy->id);
8689 err_code |= ERR_WARN;
8690 }
8691
8692 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8693 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8694 proxy_type_str(curproxy), curproxy->id);
8695 err_code |= ERR_WARN;
8696 }
8697
8698 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8699 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8700 proxy_type_str(curproxy), curproxy->id);
8701 err_code |= ERR_WARN;
8702 }
8703
Willy Tarreau87cf5142011-08-19 22:57:24 +02008704 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008705 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8706 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8707 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008708 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008709 }
8710
8711 if (curproxy->options & PR_O_ORGTO) {
8712 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8713 "originalto", proxy_type_str(curproxy), curproxy->id);
8714 err_code |= ERR_WARN;
8715 curproxy->options &= ~PR_O_ORGTO;
8716 }
8717
8718 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8719 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8720 (curproxy->cap & cfg_opts[optnum].cap) &&
8721 (curproxy->options & cfg_opts[optnum].val)) {
8722 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8723 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8724 err_code |= ERR_WARN;
8725 curproxy->options &= ~cfg_opts[optnum].val;
8726 }
8727 }
8728
8729 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8730 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8731 (curproxy->cap & cfg_opts2[optnum].cap) &&
8732 (curproxy->options2 & cfg_opts2[optnum].val)) {
8733 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8734 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8735 err_code |= ERR_WARN;
8736 curproxy->options2 &= ~cfg_opts2[optnum].val;
8737 }
8738 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008739
Willy Tarreau29fbe512015-08-20 19:35:14 +02008740#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008741 if (curproxy->conn_src.bind_hdr_occ) {
8742 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008743 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008744 proxy_type_str(curproxy), curproxy->id, curproxy->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 Tarreaue24fdfb2010-03-25 07:22:56 +01008748 }
8749
Willy Tarreaubaaee002006-06-26 02:48:02 +02008750 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008751 * ensure that we're not cross-dressing a TCP server into HTTP.
8752 */
8753 newsrv = curproxy->srv;
8754 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008755 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008756 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8757 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008758 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008759 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008760
Willy Tarreau0cec3312011-10-31 13:49:26 +01008761 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8762 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8763 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8764 err_code |= ERR_WARN;
8765 }
8766
Willy Tarreauc93cd162014-05-13 15:54:22 +02008767 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008768 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8769 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8770 err_code |= ERR_WARN;
8771 }
8772
Willy Tarreau29fbe512015-08-20 19:35:14 +02008773#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008774 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8775 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008776 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 +01008777 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008778 err_code |= ERR_WARN;
8779 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008780#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008781
8782 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8783 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8784 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8785 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8786 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8787 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",
8788 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8789 err_code |= ERR_WARN;
8790 }
8791
8792
8793 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8794 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",
8795 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8796 err_code |= ERR_WARN;
8797 }
8798 }
8799
Willy Tarreau21d2af32008-02-14 20:25:24 +01008800 newsrv = newsrv->next;
8801 }
8802
Willy Tarreaue42bd962014-09-16 16:21:19 +02008803 /* check if we have a frontend with "tcp-request content" looking at L7
8804 * with no inspect-delay
8805 */
8806 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8807 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008808 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008809 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008810 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008811 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008812 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008813 break;
8814 }
8815
8816 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8817 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8818 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8819 " This means that these rules will randomly find their contents. This can be fixed by"
8820 " setting the tcp-request inspect-delay.\n",
8821 proxy_type_str(curproxy), curproxy->id);
8822 err_code |= ERR_WARN;
8823 }
8824 }
8825
Christopher Fauletd7c91962015-04-30 11:48:27 +02008826 /* Check filter configuration, if any */
8827 cfgerr += flt_check(curproxy);
8828
Willy Tarreauc1a21672009-08-16 22:37:44 +02008829 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008830 if (!curproxy->accept)
8831 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008832
Willy Tarreauc1a21672009-08-16 22:37:44 +02008833 if (curproxy->tcp_req.inspect_delay ||
8834 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008835 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008836
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008837 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008838 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008839 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008840 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008841
8842 /* both TCP and HTTP must check switching rules */
8843 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008844
8845 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008846 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008847 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8848 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 +01008849 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008850 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8851 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008852 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008853 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008854 }
8855
8856 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008857 if (curproxy->tcp_req.inspect_delay ||
8858 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8859 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8860
Emeric Brun97679e72010-09-23 17:56:44 +02008861 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8862 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8863
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008864 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008865 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008866 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008867 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008868
8869 /* If the backend does requires RDP cookie persistence, we have to
8870 * enable the corresponding analyser.
8871 */
8872 if (curproxy->options2 & PR_O2_RDPC_PRST)
8873 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008874
8875 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008876 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008877 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8878 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 +01008879 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008880 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8881 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008882 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008883 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008884 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008885 }
8886
8887 /***********************************************************/
8888 /* At this point, target names have already been resolved. */
8889 /***********************************************************/
8890
8891 /* Check multi-process mode compatibility */
8892
8893 if (global.nbproc > 1 && global.stats_fe) {
8894 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8895 unsigned long mask;
8896
8897 mask = nbits(global.nbproc);
8898 if (global.stats_fe->bind_proc)
8899 mask &= global.stats_fe->bind_proc;
8900
8901 if (bind_conf->bind_proc)
8902 mask &= bind_conf->bind_proc;
8903
8904 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008905 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008906 break;
8907 }
8908 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8909 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");
8910 }
8911 }
8912
8913 /* Make each frontend inherit bind-process from its listeners when not specified. */
8914 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8915 if (curproxy->bind_proc)
8916 continue;
8917
8918 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8919 unsigned long mask;
8920
Willy Tarreaue428b082015-05-04 21:57:58 +02008921 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008922 curproxy->bind_proc |= mask;
8923 }
8924
8925 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008926 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008927 }
8928
8929 if (global.stats_fe) {
8930 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8931 unsigned long mask;
8932
Cyril Bonté06181952016-02-24 00:14:54 +01008933 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008934 global.stats_fe->bind_proc |= mask;
8935 }
8936 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008937 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008938 }
8939
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008940 /* propagate bindings from frontends to backends. Don't do it if there
8941 * are any fatal errors as we must not call it with unresolved proxies.
8942 */
8943 if (!cfgerr) {
8944 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8945 if (curproxy->cap & PR_CAP_FE)
8946 propagate_processes(curproxy, NULL);
8947 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008948 }
8949
8950 /* Bind each unbound backend to all processes when not specified. */
8951 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8952 if (curproxy->bind_proc)
8953 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008954 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008955 }
8956
8957 /*******************************************************/
8958 /* At this step, all proxies have a non-null bind_proc */
8959 /*******************************************************/
8960
8961 /* perform the final checks before creating tasks */
8962
8963 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8964 struct listener *listener;
8965 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008966
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008967 /* Configure SSL for each bind line.
8968 * Note: if configuration fails at some point, the ->ctx member
8969 * remains NULL so that listeners can later detach.
8970 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008971 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008972 if (bind_conf->xprt->prepare_bind_conf &&
8973 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008974 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008975 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008976
Willy Tarreaue6b98942007-10-29 01:09:36 +01008977 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008978 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008979 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008980 int nbproc;
8981
8982 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008983 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008984 nbits(global.nbproc));
8985
8986 if (!nbproc) /* no intersection between listener and frontend */
8987 nbproc = 1;
8988
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008989 if (!listener->luid) {
8990 /* listener ID not set, use automatic numbering with first
8991 * spare entry starting with next_luid.
8992 */
8993 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8994 listener->conf.id.key = listener->luid = next_id;
8995 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008996 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008997 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008998
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008999 /* enable separate counters */
9000 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01009001 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009002 if (!listener->name)
9003 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009004 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009005
Willy Tarreaue6b98942007-10-29 01:09:36 +01009006 if (curproxy->options & PR_O_TCP_NOLING)
9007 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009008 if (!listener->maxconn)
9009 listener->maxconn = curproxy->maxconn;
9010 if (!listener->backlog)
9011 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009012 if (!listener->maxaccept)
9013 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9014
9015 /* we want to have an optimal behaviour on single process mode to
9016 * maximize the work at once, but in multi-process we want to keep
9017 * some fairness between processes, so we target half of the max
9018 * number of events to be balanced over all the processes the proxy
9019 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9020 * used to disable the limit.
9021 */
9022 if (listener->maxaccept > 0) {
9023 if (nbproc > 1)
9024 listener->maxaccept = (listener->maxaccept + 1) / 2;
9025 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9026 }
9027
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009028 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009029 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009030 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009031
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009032 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009033 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009034
Willy Tarreau620408f2016-10-21 16:37:51 +02009035 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9036 listener->options |= LI_O_TCP_L5_RULES;
9037
Willy Tarreaude3041d2010-05-31 10:56:17 +02009038 if (curproxy->mon_mask.s_addr)
9039 listener->options |= LI_O_CHK_MONNET;
9040
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009041 /* smart accept mode is automatic in HTTP mode */
9042 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009043 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009044 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9045 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009046 }
9047
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009048 /* Release unused SSL configs */
9049 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009050 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9051 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009052 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009053
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009054 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009055 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009056 int count, maxproc = 0;
9057
9058 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009059 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009060 if (count > maxproc)
9061 maxproc = count;
9062 }
9063 /* backends have 0, frontends have 1 or more */
9064 if (maxproc != 1)
9065 Warning("Proxy '%s': in multi-process mode, stats will be"
9066 " limited to process assigned to the current request.\n",
9067 curproxy->id);
9068
Willy Tarreau102df612014-05-07 23:56:38 +02009069 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9070 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9071 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009072 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009073 }
Willy Tarreau102df612014-05-07 23:56:38 +02009074 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9075 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9076 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009077 }
9078 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009079
9080 /* create the task associated with the proxy */
9081 curproxy->task = task_new();
9082 if (curproxy->task) {
9083 curproxy->task->context = curproxy;
9084 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009085 } else {
9086 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9087 curproxy->id);
9088 cfgerr++;
9089 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009090 }
9091
Willy Tarreaufbb78422011-06-05 15:38:35 +02009092 /* automatically compute fullconn if not set. We must not do it in the
9093 * loop above because cross-references are not yet fully resolved.
9094 */
9095 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9096 /* If <fullconn> is not set, let's set it to 10% of the sum of
9097 * the possible incoming frontend's maxconns.
9098 */
9099 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009100 /* we have the sum of the maxconns in <total>. We only
9101 * keep 10% of that sum to set the default fullconn, with
9102 * a hard minimum of 1 (to avoid a divide by zero).
9103 */
Emeric Brun3f783572017-01-12 11:21:28 +01009104 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009105 if (!curproxy->fullconn)
9106 curproxy->fullconn = 1;
9107 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009108 }
9109
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009110 /*
9111 * Recount currently required checks.
9112 */
9113
9114 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9115 int optnum;
9116
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009117 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9118 if (curproxy->options & cfg_opts[optnum].val)
9119 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009120
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009121 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9122 if (curproxy->options2 & cfg_opts2[optnum].val)
9123 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009124 }
9125
Willy Tarreau0fca4832015-05-01 19:12:05 +02009126 /* compute the required process bindings for the peers */
9127 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9128 if (curproxy->table.peers.p)
9129 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9130
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009131 if (cfg_peers) {
9132 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009133 struct peer *p, *pb;
9134
Willy Tarreau1e273012015-05-01 19:15:17 +02009135 /* Remove all peers sections which don't have a valid listener,
9136 * which are not used by any table, or which are bound to more
9137 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009138 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009139 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009140 while (*last) {
9141 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009142
9143 if (curpeers->state == PR_STSTOPPED) {
9144 /* the "disabled" keyword was present */
9145 if (curpeers->peers_fe)
9146 stop_proxy(curpeers->peers_fe);
9147 curpeers->peers_fe = NULL;
9148 }
9149 else if (!curpeers->peers_fe) {
9150 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9151 curpeers->id, localpeer);
9152 }
David Carliere6c39412015-07-02 07:00:17 +00009153 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009154 /* either it's totally stopped or too much used */
9155 if (curpeers->peers_fe->bind_proc) {
9156 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009157 "running in different processes (%d different ones). "
9158 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009159 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009160 cfgerr++;
9161 }
9162 stop_proxy(curpeers->peers_fe);
9163 curpeers->peers_fe = NULL;
9164 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009165 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009166 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009167 last = &curpeers->next;
9168 continue;
9169 }
9170
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009171 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009172 p = curpeers->remote;
9173 while (p) {
9174 pb = p->next;
9175 free(p->id);
9176 free(p);
9177 p = pb;
9178 }
9179
9180 /* Destroy and unlink this curpeers section.
9181 * Note: curpeers is backed up into *last.
9182 */
9183 free(curpeers->id);
9184 curpeers = curpeers->next;
9185 free(*last);
9186 *last = curpeers;
9187 }
9188 }
9189
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009190 /* initialize stick-tables on backend capable proxies. This must not
9191 * be done earlier because the data size may be discovered while parsing
9192 * other proxies.
9193 */
9194 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9195 if (curproxy->state == PR_STSTOPPED)
9196 continue;
9197
9198 if (!stktable_init(&curproxy->table)) {
9199 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9200 cfgerr++;
9201 }
9202 }
9203
Simon Horman0d16a402015-01-30 11:22:58 +09009204 if (mailers) {
9205 struct mailers *curmailers = mailers, **last;
9206 struct mailer *m, *mb;
9207
9208 /* Remove all mailers sections which don't have a valid listener.
9209 * This can happen when a mailers section is never referenced.
9210 */
9211 last = &mailers;
9212 while (*last) {
9213 curmailers = *last;
9214 if (curmailers->users) {
9215 last = &curmailers->next;
9216 continue;
9217 }
9218
9219 Warning("Removing incomplete section 'mailers %s'.\n",
9220 curmailers->id);
9221
9222 m = curmailers->mailer_list;
9223 while (m) {
9224 mb = m->next;
9225 free(m->id);
9226 free(m);
9227 m = mb;
9228 }
9229
9230 /* Destroy and unlink this curmailers section.
9231 * Note: curmailers is backed up into *last.
9232 */
9233 free(curmailers->id);
9234 curmailers = curmailers->next;
9235 free(*last);
9236 *last = curmailers;
9237 }
9238 }
9239
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009240 /* Update server_state_file_name to backend name if backend is supposed to use
9241 * a server-state file locally defined and none has been provided */
9242 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9243 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9244 curproxy->server_state_file_name == NULL)
9245 curproxy->server_state_file_name = strdup(curproxy->id);
9246 }
9247
Willy Tarreau34eb6712011-10-24 18:15:04 +02009248 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009249 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009250 MEM_F_SHARED);
9251
Willy Tarreaubb925012009-07-23 13:36:36 +02009252 if (cfgerr > 0)
9253 err_code |= ERR_ALERT | ERR_FATAL;
9254 out:
9255 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009256}
9257
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009258/*
9259 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9260 * parsing sessions.
9261 */
9262void cfg_register_keywords(struct cfg_kw_list *kwl)
9263{
9264 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9265}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009266
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009267/*
9268 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9269 */
9270void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9271{
9272 LIST_DEL(&kwl->list);
9273 LIST_INIT(&kwl->list);
9274}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009275
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009276/* this function register new section in the haproxy configuration file.
9277 * <section_name> is the name of this new section and <section_parser>
9278 * is the called parser. If two section declaration have the same name,
9279 * only the first declared is used.
9280 */
9281int cfg_register_section(char *section_name,
9282 int (*section_parser)(const char *, int, char **, int))
9283{
9284 struct cfg_section *cs;
9285
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009286 list_for_each_entry(cs, &sections, list) {
9287 if (strcmp(cs->section_name, section_name) == 0) {
9288 Alert("register section '%s': already registered.\n", section_name);
9289 return 0;
9290 }
9291 }
9292
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009293 cs = calloc(1, sizeof(*cs));
9294 if (!cs) {
9295 Alert("register section '%s': out of memory.\n", section_name);
9296 return 0;
9297 }
9298
9299 cs->section_name = section_name;
9300 cs->section_parser = section_parser;
9301
9302 LIST_ADDQ(&sections, &cs->list);
9303
9304 return 1;
9305}
9306
Willy Tarreaubaaee002006-06-26 02:48:02 +02009307/*
David Carlier845efb52015-09-25 11:49:18 +01009308 * free all config section entries
9309 */
9310void cfg_unregister_sections(void)
9311{
9312 struct cfg_section *cs, *ics;
9313
9314 list_for_each_entry_safe(cs, ics, &sections, list) {
9315 LIST_DEL(&cs->list);
9316 free(cs);
9317 }
9318}
9319
Christopher Faulet7110b402016-10-26 11:09:44 +02009320void cfg_backup_sections(struct list *backup_sections)
9321{
9322 struct cfg_section *cs, *ics;
9323
9324 list_for_each_entry_safe(cs, ics, &sections, list) {
9325 LIST_DEL(&cs->list);
9326 LIST_ADDQ(backup_sections, &cs->list);
9327 }
9328}
9329
9330void cfg_restore_sections(struct list *backup_sections)
9331{
9332 struct cfg_section *cs, *ics;
9333
9334 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9335 LIST_DEL(&cs->list);
9336 LIST_ADDQ(&sections, &cs->list);
9337 }
9338}
9339
Willy Tarreau659fbf02016-05-26 17:55:28 +02009340__attribute__((constructor))
9341static void cfgparse_init(void)
9342{
9343 /* Register internal sections */
9344 cfg_register_section("listen", cfg_parse_listen);
9345 cfg_register_section("frontend", cfg_parse_listen);
9346 cfg_register_section("backend", cfg_parse_listen);
9347 cfg_register_section("defaults", cfg_parse_listen);
9348 cfg_register_section("global", cfg_parse_global);
9349 cfg_register_section("userlist", cfg_parse_users);
9350 cfg_register_section("peers", cfg_parse_peers);
9351 cfg_register_section("mailers", cfg_parse_mailers);
9352 cfg_register_section("namespace_list", cfg_parse_netns);
9353 cfg_register_section("resolvers", cfg_parse_resolvers);
9354}
9355
David Carlier845efb52015-09-25 11:49:18 +01009356/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009357 * Local variables:
9358 * c-indent-level: 8
9359 * c-basic-offset: 8
9360 * End:
9361 */