blob: e29ae53daa56ea2094d585c7616866e57598349b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020076#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100205char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100241 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200288 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200291 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200298 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100325 * Report an error in <msg> when there are too many arguments. This version is
326 * intended to be used by keyword parsers so that the message will be included
327 * into the general error message. The index is the current keyword in args.
328 * Return 0 if the number of argument is correct, otherwise build a message and
329 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
330 * message may also be null, it will simply not be produced (useful to check only).
331 * <msg> and <err_code> are only affected on error.
332 */
333int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
334{
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 if (msg) {
341 *msg = NULL;
342 memprintf(msg, "%s", args[0]);
343 for (i = 1; i <= index; i++)
344 memprintf(msg, "%s %s", *msg, args[i]);
345
346 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
347 }
348 if (err_code)
349 *err_code |= ERR_ALERT | ERR_FATAL;
350
351 return 1;
352}
353
354/*
355 * same as too_many_args_idx with a 0 index
356 */
357int too_many_args(int maxarg, char **args, char **msg, int *err_code)
358{
359 return too_many_args_idx(maxarg, 0, args, msg, err_code);
360}
361
362/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200363 * Report a fatal Alert when there is too much arguments
364 * The index is the current keyword in args
365 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
366 * Fill err_code with an ERR_ALERT and an ERR_FATAL
367 */
368int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
369{
370 char *kw = NULL;
371 int i;
372
373 if (!*args[index + maxarg + 1])
374 return 0;
375
376 memprintf(&kw, "%s", args[0]);
377 for (i = 1; i <= index; i++) {
378 memprintf(&kw, "%s %s", kw, args[i]);
379 }
380
381 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
382 free(kw);
383 *err_code |= ERR_ALERT | ERR_FATAL;
384 return 1;
385}
386
387/*
388 * same as alertif_too_many_args_idx with a 0 index
389 */
390int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
391{
392 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
393}
394
Willy Tarreau620408f2016-10-21 16:37:51 +0200395/* Report a warning if a rule is placed after a 'tcp-request session' rule.
396 * Return 1 if the warning has been emitted, otherwise 0.
397 */
398int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
399{
400 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
401 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
402 file, line, arg);
403 return 1;
404 }
405 return 0;
406}
407
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200408/* Report a warning if a rule is placed after a 'tcp-request content' rule.
409 * Return 1 if the warning has been emitted, otherwise 0.
410 */
411int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
412{
413 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
414 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
415 file, line, arg);
416 return 1;
417 }
418 return 0;
419}
420
Willy Tarreau61d18892009-03-31 10:49:21 +0200421/* Report a warning if a rule is placed after a 'block' rule.
422 * Return 1 if the warning has been emitted, otherwise 0.
423 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100424int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200425{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200426 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200427 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
428 file, line, arg);
429 return 1;
430 }
431 return 0;
432}
433
Willy Tarreau5002f572014-04-23 01:32:02 +0200434/* Report a warning if a rule is placed after an 'http_request' rule.
435 * Return 1 if the warning has been emitted, otherwise 0.
436 */
437int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
438{
439 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
440 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
441 file, line, arg);
442 return 1;
443 }
444 return 0;
445}
446
Willy Tarreau61d18892009-03-31 10:49:21 +0200447/* Report a warning if a rule is placed after a reqrewrite rule.
448 * Return 1 if the warning has been emitted, otherwise 0.
449 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
452 if (proxy->req_exp) {
453 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
454 file, line, arg);
455 return 1;
456 }
457 return 0;
458}
459
460/* Report a warning if a rule is placed after a reqadd rule.
461 * Return 1 if the warning has been emitted, otherwise 0.
462 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100463int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200464{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100465 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
467 file, line, arg);
468 return 1;
469 }
470 return 0;
471}
472
473/* Report a warning if a rule is placed after a redirect rule.
474 * Return 1 if the warning has been emitted, otherwise 0.
475 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
479 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
480 file, line, arg);
481 return 1;
482 }
483 return 0;
484}
485
486/* Report a warning if a rule is placed after a 'use_backend' rule.
487 * Return 1 if the warning has been emitted, otherwise 0.
488 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
491 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
492 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
493 file, line, arg);
494 return 1;
495 }
496 return 0;
497}
498
Willy Tarreauee445d92014-04-23 01:39:04 +0200499/* Report a warning if a rule is placed after a 'use-server' rule.
500 * Return 1 if the warning has been emitted, otherwise 0.
501 */
502int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
503{
504 if (!LIST_ISEMPTY(&proxy->server_rules)) {
505 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
506 file, line, arg);
507 return 1;
508 }
509 return 0;
510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a redirect rule is dangerously placed */
513int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200516 warnif_rule_after_use_server(proxy, file, line, arg);
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a reqadd rule is dangerously placed */
520int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_redirect(proxy, file, line, arg) ||
523 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqxxx rule is dangerously placed */
527int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
530 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200531}
532
533/* report a warning if an http-request rule is dangerously placed */
534int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
535{
Willy Tarreau61d18892009-03-31 10:49:21 +0200536 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100537 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a block rule is dangerously placed */
541int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_http_req(proxy, file, line, arg) ||
544 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a "tcp request content" rule is dangerously placed */
548int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_block(proxy, file, line, arg) ||
551 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request session" rule is dangerously placed */
555int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
558 warnif_misplaced_tcp_cont(proxy, file, line, arg);
559}
560
561/* report a warning if a "tcp request connection" rule is dangerously placed */
562int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
563{
564 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200566}
567
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568/* Report it if a request ACL condition uses some keywords that are incompatible
569 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
570 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
571 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 return 0;
580
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 acl = acl_cond_conflicts(cond, where);
582 if (acl) {
583 if (acl->name && *acl->name)
584 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
585 file, line, acl->name, sample_ckp_names(where));
586 else
587 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200588 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 return ERR_WARN;
590 }
591 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100592 return 0;
593
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 if (acl->name && *acl->name)
595 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200596 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100597 else
598 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200599 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100600 return ERR_WARN;
601}
602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 * parse a line in a <global> section. Returns the error code, 0 if OK, or
605 * any combination of :
606 * - ERR_ABORT: must abort ASAP
607 * - ERR_FATAL: we can continue parsing but not start the service
608 * - ERR_WARN: a warning has been emitted
609 * - ERR_ALERT: an alert has been emitted
610 * Only the two first ones can stop processing, the two others are just
611 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200613int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614{
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200616 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
618 if (!strcmp(args[0], "global")) { /* new section */
619 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200620 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200624 if (alertif_too_many_args(0, file, linenum, args, &err_code))
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 global.mode |= MODE_DAEMON;
627 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200628 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200631 if (*args[1]) {
632 if (!strcmp(args[1], "exit-on-failure")) {
633 global.tune.options |= GTUNE_EXIT_ONFAILURE;
634 } else {
635 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
638 }
639 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200640 global.mode |= MODE_MWORKER;
641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 global.mode |= MODE_DEBUG;
646 }
647 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100660 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100665 global.tune.options &= ~GTUNE_USE_SPLICE;
666 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200670 global.tune.options &= ~GTUNE_USE_GAI;
671 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000672 else if (!strcmp(args[0], "noreuseport")) {
673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
675 global.tune.options &= ~GTUNE_USE_REUSEPORT;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_QUIET;
681 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 if (global.tune.maxpollevents != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200694 }
695 global.tune.maxpollevents = atol(args[1]);
696 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 if (global.tune.maxaccept != 0) {
701 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100709 }
710 global.tune.maxaccept = atol(args[1]);
711 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.chksize = atol(args[1]);
721 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100722 else if (!strcmp(args[0], "tune.recv_enough")) {
723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.recv_enough = atol(args[1]);
731 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.buf_limit = atol(args[1]);
741 if (global.tune.buf_limit) {
742 if (global.tune.buf_limit < 3)
743 global.tune.buf_limit = 3;
744 if (global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
746 }
747 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100748 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.reserved_bufs = atol(args[1]);
757 if (global.tune.reserved_bufs < 2)
758 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100759 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
760 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200771 if (global.tune.bufsize <= 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100776 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100777 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
779 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200788 if (global.tune.maxrewrite < 0) {
789 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200793 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100794 else if (!strcmp(args[0], "tune.idletimer")) {
795 unsigned int idle;
796 const char *res;
797
William Lallemand1a748ae2015-05-19 16:37:23 +0200798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
799 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805
806 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
807 if (res) {
808 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
809 file, linenum, *res, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813
814 if (idle > 65535) {
815 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.idle_timer = idle;
820 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.client_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.client_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.server_rcvbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.server_rcvbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.client_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.client_sndbuf = atol(args[1]);
865 }
866 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100869 if (global.tune.server_sndbuf != 0) {
870 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT;
872 goto out;
873 }
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.server_sndbuf = atol(args[1]);
880 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200881 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.pipesize = atol(args[1]);
890 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100891 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.cookie_len = atol(args[1]) + 1;
900 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200901 else if (!strcmp(args[0], "tune.http.logurilen")) {
902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.requri_len = atol(args[1]) + 1;
910 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200911 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200919 global.tune.max_http_hdr = atoi(args[1]);
920 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
921 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200926 }
William Lallemandf3747832012-11-09 12:33:10 +0100927 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100930 if (*args[1]) {
931 global.tune.comp_maxlevel = atoi(args[1]);
932 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
933 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 } else {
939 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
940 file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200945 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
946 if (*args[1]) {
947 global.tune.pattern_cache = atoi(args[1]);
948 if (global.tune.pattern_cache < 0) {
949 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
950 file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 } else {
955 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
956 file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200965 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100974 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
975 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]);
976 err_code |= ERR_WARN;
977 goto out;
978 }
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100994 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
995 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]);
996 err_code |= ERR_WARN;
997 goto out;
998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
Simon Horman98637e52014-06-20 12:30:16 +09001000 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1002 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001003 global.external_check = 1;
1004 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001005 /* user/group name handling */
1006 else if (!strcmp(args[0], "user")) {
1007 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001008 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1009 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001010 if (global.uid != 0) {
1011 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT;
1013 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001014 }
1015 errno = 0;
1016 ha_user = getpwnam(args[1]);
1017 if (ha_user != NULL) {
1018 global.uid = (int)ha_user->pw_uid;
1019 }
1020 else {
1021 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 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001023 }
1024 }
1025 else if (!strcmp(args[0], "group")) {
1026 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001027 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1028 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001029 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001030 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT;
1032 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 }
1034 errno = 0;
1035 ha_group = getgrnam(args[1]);
1036 if (ha_group != NULL) {
1037 global.gid = (int)ha_group->gr_gid;
1038 }
1039 else {
1040 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 +02001041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001042 }
1043 }
1044 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001054 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1055 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1056 file, linenum, args[0], LONGBITS, global.nbproc);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.maxconn != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.maxconn = atol(args[1]);
1075#ifdef SYSTEM_MAXCONN
1076 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1077 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);
1078 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081#endif /* SYSTEM_MAXCONN */
1082 }
Emeric Brun850efd52014-01-29 12:24:34 +01001083 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 if (strcmp(args[1],"none") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1093 else if (strcmp(args[1],"required") == 0)
1094 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1095 else {
1096 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001101 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1103 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001104 if (global.cps_lim != 0) {
1105 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT;
1107 goto out;
1108 }
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 global.cps_lim = atol(args[1]);
1115 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001116 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001119 if (global.sps_lim != 0) {
1120 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT;
1122 goto out;
1123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
1128 }
1129 global.sps_lim = atol(args[1]);
1130 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001131 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1133 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001134 if (global.ssl_lim != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1136 err_code |= ERR_ALERT;
1137 goto out;
1138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
1143 }
1144 global.ssl_lim = atol(args[1]);
1145 }
William Lallemandd85f9172012-11-09 17:05:39 +01001146 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
1153 }
1154 global.comp_rate_lim = atoi(args[1]) * 1024;
1155 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001156 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001159 if (global.maxpipes != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001168 }
1169 global.maxpipes = atol(args[1]);
1170 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001171 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
William Lallemande3a7d992012-11-20 11:25:20 +01001179 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001180 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001181 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001190 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001191 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (global.rlimit_nofile != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
1210 global.rlimit_nofile = atol(args[1]);
1211 }
1212 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 if (global.chroot != NULL) {
1216 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001217 err_code |= ERR_ALERT;
1218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 }
1225 global.chroot = strdup(args[1]);
1226 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001227 else if (!strcmp(args[0], "description")) {
1228 int i, len=0;
1229 char *d;
1230
1231 if (!*args[1]) {
1232 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1233 file, linenum, args[0]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
Willy Tarreau348acfe2014-04-14 15:00:39 +02001238 for (i = 1; *args[i]; i++)
1239 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001240
1241 if (global.desc)
1242 free(global.desc);
1243
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001244 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001245
Willy Tarreau348acfe2014-04-14 15:00:39 +02001246 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1247 for (i = 2; *args[i]; i++)
1248 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001249 }
1250 else if (!strcmp(args[0], "node")) {
1251 int i;
1252 char c;
1253
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
1256
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001257 for (i=0; args[1][i]; i++) {
1258 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001259 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1260 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001261 break;
1262 }
1263
1264 if (!i || args[1][i]) {
1265 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1266 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1267 file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if (global.node)
1273 free(global.node);
1274
1275 global.node = strdup(args[1]);
1276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (global.pidfile != NULL) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001282 err_code |= ERR_ALERT;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
1290 global.pidfile = strdup(args[1]);
1291 }
Emeric Bruned760922010-10-22 17:59:25 +02001292 else if (!strcmp(args[0], "unix-bind")) {
1293 int cur_arg = 1;
1294 while (*(args[cur_arg])) {
1295 if (!strcmp(args[cur_arg], "prefix")) {
1296 if (global.unix_bind.prefix != NULL) {
1297 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1298 err_code |= ERR_ALERT;
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (*(args[cur_arg+1]) == 0) {
1304 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "mode")) {
1314
1315 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1316 cur_arg += 2;
1317 continue;
1318 }
1319
1320 if (!strcmp(args[cur_arg], "uid")) {
1321
1322 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1323 cur_arg += 2;
1324 continue;
1325 }
1326
1327 if (!strcmp(args[cur_arg], "gid")) {
1328
1329 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1330 cur_arg += 2;
1331 continue;
1332 }
1333
1334 if (!strcmp(args[cur_arg], "user")) {
1335 struct passwd *user;
1336
1337 user = getpwnam(args[cur_arg + 1]);
1338 if (!user) {
1339 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1340 file, linenum, args[0], args[cur_arg + 1 ]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 global.unix_bind.ux.uid = user->pw_uid;
1346 cur_arg += 2;
1347 continue;
1348 }
1349
1350 if (!strcmp(args[cur_arg], "group")) {
1351 struct group *group;
1352
1353 group = getgrnam(args[cur_arg + 1]);
1354 if (!group) {
1355 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1356 file, linenum, args[0], args[cur_arg + 1 ]);
1357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
1359 }
1360
1361 global.unix_bind.ux.gid = group->gr_gid;
1362 cur_arg += 2;
1363 continue;
1364 }
1365
Willy Tarreaub48f9582011-09-05 01:17:06 +02001366 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1373 /* delete previous herited or defined syslog servers */
1374 struct logsrv *back;
1375 struct logsrv *tmp;
1376
1377 if (*(args[1]) != 0) {
1378 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
1382
1383 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1384 LIST_DEL(&tmp->list);
1385 free(tmp);
1386 }
1387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001389 struct sockaddr_storage *sk;
1390 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001392 int arg = 0;
1393 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001394
William Lallemand1a748ae2015-05-19 16:37:23 +02001395 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1396 goto out;
1397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 if (*(args[1]) == 0 || *(args[2]) == 0) {
1399 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Vincent Bernat02779b62016-04-03 13:48:43 +02001404 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001405
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 /* just after the address, a length may be specified */
1407 if (strcmp(args[arg+2], "len") == 0) {
1408 len = atoi(args[arg+3]);
1409 if (len < 80 || len > 65535) {
1410 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1411 file, linenum, args[arg+3]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415 logsrv->maxlen = len;
1416
1417 /* skip these two args */
1418 arg += 2;
1419 }
1420 else
1421 logsrv->maxlen = MAX_SYSLOG_LEN;
1422
1423 if (logsrv->maxlen > global.max_syslog_len) {
1424 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001425 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1426 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1427 logline = my_realloc2(logline, global.max_syslog_len + 1);
1428 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001429 }
1430
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 /* after the length, a format may be specified */
1432 if (strcmp(args[arg+2], "format") == 0) {
1433 logsrv->format = get_log_format(args[arg+3]);
1434 if (logsrv->format < 0) {
1435 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001437 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001438 goto out;
1439 }
1440
1441 /* skip these two args */
1442 arg += 2;
1443 }
1444
David Carlier97880bb2016-04-08 10:35:26 +01001445 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1446 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001447 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001448 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001449
Willy Tarreau18324f52014-06-27 18:10:07 +02001450 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001451 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001452 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001453 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001454 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001458 if (*(args[arg+3])) {
1459 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001460 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001463 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 }
1466
William Lallemand0f99e342011-10-12 17:50:54 +02001467 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001468 if (*(args[arg+4])) {
1469 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001470 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001471 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001472 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001473 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001474 }
1475 }
1476
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001477 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001478 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001479 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001481 free(logsrv);
1482 goto out;
1483 }
1484 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001485
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001486 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487 if (port1 != port2) {
1488 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1489 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001490 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001491 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001492 goto out;
1493 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001494
William Lallemand0f99e342011-10-12 17:50:54 +02001495 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001496 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001497 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
William Lallemand0f99e342011-10-12 17:50:54 +02001500 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001501 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001502 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1503 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001504
1505 if (global.log_send_hostname != NULL) {
1506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1507 err_code |= ERR_ALERT;
1508 goto out;
1509 }
1510
1511 if (*(args[1]))
1512 name = args[1];
1513 else
1514 name = hostname;
1515
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001516 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001517 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001518 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001519 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1520 if (global.server_state_base != NULL) {
1521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1522 err_code |= ERR_ALERT;
1523 goto out;
1524 }
1525
1526 if (!*(args[1])) {
1527 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1528 err_code |= ERR_FATAL;
1529 goto out;
1530 }
1531
1532 global.server_state_base = strdup(args[1]);
1533 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001534 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1535 if (global.server_state_file != NULL) {
1536 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1537 err_code |= ERR_ALERT;
1538 goto out;
1539 }
1540
1541 if (!*(args[1])) {
1542 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1543 err_code |= ERR_FATAL;
1544 goto out;
1545 }
1546
1547 global.server_state_file = strdup(args[1]);
1548 }
Kevinm48936af2010-12-22 16:08:21 +00001549 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001550 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1551 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001552 if (*(args[1]) == 0) {
1553 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001557 chunk_destroy(&global.log_tag);
1558 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001559 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1562 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001563 if (global.spread_checks != 0) {
1564 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001565 err_code |= ERR_ALERT;
1566 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001567 }
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001572 }
1573 global.spread_checks = atol(args[1]);
1574 if (global.spread_checks < 0 || global.spread_checks > 50) {
1575 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001579 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1580 const char *err;
1581 unsigned int val;
1582
William Lallemand1a748ae2015-05-19 16:37:23 +02001583 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1584 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001585 if (*(args[1]) == 0) {
1586 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1592 if (err) {
1593 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 }
1596 global.max_spread_checks = val;
1597 if (global.max_spread_checks < 0) {
1598 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 }
1601 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001602 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1603#ifdef USE_CPU_AFFINITY
1604 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001605 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 unsigned long cpus = 0;
1607
1608 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001611 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 proc = atol(args[1]);
1616 if (proc >= 1 && proc <= LONGBITS)
1617 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001618 }
1619
1620 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 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",
1622 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
1627 cur_arg = 2;
1628 while (*args[cur_arg]) {
1629 unsigned int low, high;
1630
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001631 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001632 char *dash = strchr(args[cur_arg], '-');
1633
1634 low = high = str2uic(args[cur_arg]);
1635 if (dash)
1636 high = str2uic(dash + 1);
1637
1638 if (high < low) {
1639 unsigned int swap = low;
1640 low = high;
1641 high = swap;
1642 }
1643
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001644 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001645 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001646 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
1649 }
1650
1651 while (low <= high)
1652 cpus |= 1UL << low++;
1653 }
1654 else {
1655 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1656 file, linenum, args[0], args[cur_arg]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660 cur_arg++;
1661 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001662 for (i = 0; i < LONGBITS; i++)
1663 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001664 global.cpu_map[i] = cpus;
1665#else
1666 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669#endif
1670 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001671 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1672 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1673 goto out;
1674
1675 if (*(args[2]) == 0) {
1676 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680
1681 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1682 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1683 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687 }
1688 else if (!strcmp(args[0], "unsetenv")) {
1689 int arg;
1690
1691 if (*(args[1]) == 0) {
1692 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
1697 for (arg = 1; *args[arg]; arg++) {
1698 if (unsetenv(args[arg]) != 0) {
1699 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703 }
1704 }
1705 else if (!strcmp(args[0], "resetenv")) {
1706 extern char **environ;
1707 char **env = environ;
1708
1709 /* args contain variable names to keep, one per argument */
1710 while (*env) {
1711 int arg;
1712
1713 /* look for current variable in among all those we want to keep */
1714 for (arg = 1; *args[arg]; arg++) {
1715 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1716 (*env)[strlen(args[arg])] == '=')
1717 break;
1718 }
1719
1720 /* delete this variable */
1721 if (!*args[arg]) {
1722 char *delim = strchr(*env, '=');
1723
1724 if (!delim || delim - *env >= trash.size) {
1725 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
1730 memcpy(trash.str, *env, delim - *env);
1731 trash.str[delim - *env] = 0;
1732
1733 if (unsetenv(trash.str) != 0) {
1734 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
1737 }
1738 }
1739 else
1740 env++;
1741 }
1742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001744 struct cfg_kw_list *kwl;
1745 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001746 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001747
1748 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1749 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1750 if (kwl->kw[index].section != CFG_GLOBAL)
1751 continue;
1752 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001753 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001754 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001755 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001758 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001759 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001760 err_code |= ERR_WARN;
1761 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001762 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001764 }
1765 }
1766 }
1767
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001771
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001773 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001774 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775}
1776
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001777void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001779 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 defproxy.mode = PR_MODE_TCP;
1781 defproxy.state = PR_STNEW;
1782 defproxy.maxconn = cfg_maxpconn;
1783 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001784 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001785 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001786
Simon Horman66183002013-02-23 10:16:43 +09001787 defproxy.defsrv.check.inter = DEF_CHKINTR;
1788 defproxy.defsrv.check.fastinter = 0;
1789 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001790 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1791 defproxy.defsrv.agent.fastinter = 0;
1792 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001793 defproxy.defsrv.check.rise = DEF_RISETIME;
1794 defproxy.defsrv.check.fall = DEF_FALLTIME;
1795 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1796 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001797 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001798 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 defproxy.defsrv.maxqueue = 0;
1800 defproxy.defsrv.minconn = 0;
1801 defproxy.defsrv.maxconn = 0;
1802 defproxy.defsrv.slowstart = 0;
1803 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1804 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1805 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001806
1807 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001808 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809}
1810
Willy Tarreauade5ec42010-01-28 19:33:49 +01001811
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1813 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1814 * ERR_FATAL in case of error.
1815 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816static int create_cond_regex_rule(const char *file, int line,
1817 struct proxy *px, int dir, int action, int flags,
1818 const char *cmd, const char *reg, const char *repl,
1819 const char **cond_start)
1820{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001822 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001826 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001827 int cs;
1828 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001829
1830 if (px == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833 goto err;
1834 }
1835
1836 if (*reg == 0) {
1837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001838 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001839 goto err;
1840 }
1841
Christopher Faulet898566e2016-10-26 11:06:28 +02001842 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001844
Willy Tarreau5321c422010-01-28 20:35:13 +01001845 if (cond_start &&
1846 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001847 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1848 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1849 file, line, cmd, errmsg);
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 }
1854 else if (cond_start && **cond_start) {
1855 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1856 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001858 goto err;
1859 }
1860
Willy Tarreau63af98d2014-05-18 08:11:41 +02001861 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001862 (dir == SMP_OPT_DIR_REQ) ?
1863 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1864 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1865 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868 if (!preg) {
1869 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001870 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871 goto err;
1872 }
1873
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 cs = !(flags & REG_ICASE);
1875 cap = !(flags & REG_NOSUB);
1876 error = NULL;
1877 if (!regex_comp(reg, preg, cs, cap, &error)) {
1878 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1879 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001880 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881 goto err;
1882 }
1883
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001884 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001885 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886 if (repl && err) {
1887 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1888 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001889 ret_code |= ERR_ALERT | ERR_FATAL;
1890 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891 }
1892
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001893 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_WARN;
1895
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900 err:
1901 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001902 free(errmsg);
1903 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904}
1905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906/*
William Lallemand51097192015-04-14 16:35:22 +02001907 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001908 * Returns the error code, 0 if OK, or any combination of :
1909 * - ERR_ABORT: must abort ASAP
1910 * - ERR_FATAL: we can continue parsing but not start the service
1911 * - ERR_WARN: a warning has been emitted
1912 * - ERR_ALERT: an alert has been emitted
1913 * Only the two first ones can stop processing, the two others are just
1914 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001916int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1917{
1918 static struct peers *curpeers = NULL;
1919 struct peer *newpeer = NULL;
1920 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001921 struct bind_conf *bind_conf;
1922 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001924 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
1926 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001927 if (!*args[1]) {
1928 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001929 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 goto out;
1931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001932
William Lallemand6e62fb62015-04-28 16:55:23 +02001933 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1934 goto out;
1935
Emeric Brun32da3c42010-09-23 18:39:19 +02001936 err = invalid_char(args[1]);
1937 if (err) {
1938 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1939 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001940 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001941 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 }
1943
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001944 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001945 /*
1946 * If there are two proxies with the same name only following
1947 * combinations are allowed:
1948 */
1949 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001950 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 +02001951 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001953 }
1954 }
1955
Vincent Bernat02779b62016-04-03 13:48:43 +02001956 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1958 err_code |= ERR_ALERT | ERR_ABORT;
1959 goto out;
1960 }
1961
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001962 curpeers->next = cfg_peers;
1963 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001964 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 curpeers->conf.line = linenum;
1966 curpeers->last_change = now.tv_sec;
1967 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001968 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001969 }
1970 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001971 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001972 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001973 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001974
1975 if (!*args[2]) {
1976 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1977 file, linenum, args[0]);
1978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
1980 }
1981
1982 err = invalid_char(args[1]);
1983 if (err) {
1984 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1985 file, linenum, *err, args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
Vincent Bernat02779b62016-04-03 13:48:43 +02001990 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1992 err_code |= ERR_ALERT | ERR_ABORT;
1993 goto out;
1994 }
1995
1996 /* the peers are linked backwards first */
1997 curpeers->count++;
1998 newpeer->next = curpeers->remote;
1999 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002000 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 newpeer->conf.line = linenum;
2002
2003 newpeer->last_change = now.tv_sec;
2004 newpeer->id = strdup(args[1]);
2005
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002006 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002007 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002008 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002011 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002012
2013 proto = protocol_by_family(sk->ss_family);
2014 if (!proto || !proto->connect) {
2015 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2016 file, linenum, args[0], args[1]);
2017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002020
2021 if (port1 != port2) {
2022 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed 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 }
2027
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028 if (!port1) {
2029 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2030 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002037 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002038 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002039
Emeric Brun32da3c42010-09-23 18:39:19 +02002040 if (strcmp(newpeer->id, localpeer) == 0) {
2041 /* Current is local peer, it define a frontend */
2042 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002043 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
2045 if (!curpeers->peers_fe) {
2046 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2048 err_code |= ERR_ALERT | ERR_ABORT;
2049 goto out;
2050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
Willy Tarreau237250c2011-07-29 01:49:03 +02002052 init_new_proxy(curpeers->peers_fe);
2053 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002054 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002055 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2056 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002057 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002059 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060
Willy Tarreau902636f2013-03-10 19:44:48 +01002061 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2062 if (errmsg && *errmsg) {
2063 indent_msg(&errmsg, 2);
2064 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002065 }
2066 else
2067 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2068 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 err_code |= ERR_FATAL;
2070 goto out;
2071 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002072
2073 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002074 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002075 l->maxconn = curpeers->peers_fe->maxconn;
2076 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002077 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002078 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002079 l->analysers |= curpeers->peers_fe->fe_req_ana;
2080 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002081 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2082 global.maxsock += l->maxconn;
2083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002085 else {
2086 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2087 file, linenum, args[0], args[1],
2088 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2089 err_code |= ERR_FATAL;
2090 goto out;
2091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 }
2093 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002094 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2095 curpeers->state = PR_STSTOPPED;
2096 }
2097 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2098 curpeers->state = PR_STNEW;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 else if (*args[0] != 0) {
2101 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
2105
2106out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002107 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 return err_code;
2109}
2110
Baptiste Assmann325137d2015-04-13 23:40:55 +02002111/*
2112 * Parse a <resolvers> section.
2113 * Returns the error code, 0 if OK, or any combination of :
2114 * - ERR_ABORT: must abort ASAP
2115 * - ERR_FATAL: we can continue parsing but not start the service
2116 * - ERR_WARN: a warning has been emitted
2117 * - ERR_ALERT: an alert has been emitted
2118 * Only the two first ones can stop processing, the two others are just
2119 * indicators.
2120 */
2121int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2122{
2123 static struct dns_resolvers *curr_resolvers = NULL;
2124 struct dns_nameserver *newnameserver = NULL;
2125 const char *err;
2126 int err_code = 0;
2127 char *errmsg = NULL;
2128
2129 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2139 file, linenum, *err, args[0], args[1]);
2140 err_code |= ERR_ALERT | ERR_ABORT;
2141 goto out;
2142 }
2143
2144 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2145 /* Error if two resolvers owns the same name */
2146 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2147 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2148 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 }
2151 }
2152
Vincent Bernat02779b62016-04-03 13:48:43 +02002153 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2155 err_code |= ERR_ALERT | ERR_ABORT;
2156 goto out;
2157 }
2158
2159 /* default values */
2160 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2161 curr_resolvers->conf.file = strdup(file);
2162 curr_resolvers->conf.line = linenum;
2163 curr_resolvers->id = strdup(args[1]);
2164 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002165 /* default hold period for nx, other, refuse and timeout is 30s */
2166 curr_resolvers->hold.nx = 30000;
2167 curr_resolvers->hold.other = 30000;
2168 curr_resolvers->hold.refused = 30000;
2169 curr_resolvers->hold.timeout = 30000;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002170 curr_resolvers->hold.obsolete = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002171 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002172 curr_resolvers->hold.valid = 10000;
2173 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002174 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002175 /* default resolution pool size */
2176 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002177 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002178 LIST_INIT(&curr_resolvers->resolution.curr);
2179 LIST_INIT(&curr_resolvers->resolution.wait);
2180 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002181 }
2182 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2183 struct sockaddr_storage *sk;
2184 int port1, port2;
2185 struct protocol *proto;
2186
2187 if (!*args[2]) {
2188 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2189 file, linenum, args[0]);
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
2194 err = invalid_char(args[1]);
2195 if (err) {
2196 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2197 file, linenum, *err, args[1]);
2198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
2200 }
2201
Baptiste Assmanna315c552015-11-02 22:55:49 +01002202 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2203 /* Error if two resolvers owns the same name */
2204 if (strcmp(newnameserver->id, args[1]) == 0) {
2205 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2206 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 }
2209 }
2210
Vincent Bernat02779b62016-04-03 13:48:43 +02002211 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2213 err_code |= ERR_ALERT | ERR_ABORT;
2214 goto out;
2215 }
2216
2217 /* the nameservers are linked backward first */
2218 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2219 curr_resolvers->count_nameservers++;
2220 newnameserver->resolvers = curr_resolvers;
2221 newnameserver->conf.file = strdup(file);
2222 newnameserver->conf.line = linenum;
2223 newnameserver->id = strdup(args[1]);
2224
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002225 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002226 if (!sk) {
2227 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231
2232 proto = protocol_by_family(sk->ss_family);
2233 if (!proto || !proto->connect) {
2234 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2235 file, linenum, args[0], args[1]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239
2240 if (port1 != port2) {
2241 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2242 file, linenum, args[0], args[1], args[2]);
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002247 if (!port1 && !port2) {
2248 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2249 file, linenum, args[0], args[1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
Baptiste Assmann325137d2015-04-13 23:40:55 +02002254 newnameserver->addr = *sk;
2255 }
2256 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2257 const char *res;
2258 unsigned int time;
2259
2260 if (!*args[2]) {
2261 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2262 file, linenum, args[0]);
2263 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
2266 }
2267 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2268 if (res) {
2269 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2270 file, linenum, *res, args[0]);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
2273 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002274 if (strcmp(args[1], "nx") == 0)
2275 curr_resolvers->hold.nx = time;
2276 else if (strcmp(args[1], "other") == 0)
2277 curr_resolvers->hold.other = time;
2278 else if (strcmp(args[1], "refused") == 0)
2279 curr_resolvers->hold.refused = time;
2280 else if (strcmp(args[1], "timeout") == 0)
2281 curr_resolvers->hold.timeout = time;
2282 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002283 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002284 else if (strcmp(args[1], "obsolete") == 0)
2285 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002287 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002288 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
2291 }
2292
2293 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002294 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2295 if (!*args[1]) {
2296 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2297 file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301 curr_resolvers->resolution_pool_size = atoi(args[1]);
2302 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002303 else if (strcmp(args[0], "resolve_retries") == 0) {
2304 if (!*args[1]) {
2305 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2306 file, linenum, args[0]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310 curr_resolvers->resolve_retries = atoi(args[1]);
2311 }
2312 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002313 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002314 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2315 file, linenum, args[0]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002319 else if (strcmp(args[1], "retry") == 0) {
2320 const char *res;
2321 unsigned int timeout_retry;
2322
2323 if (!*args[2]) {
2324 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2325 file, linenum, args[0], args[1]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2330 if (res) {
2331 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2332 file, linenum, *res, args[0], args[1]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336 curr_resolvers->timeout.retry = timeout_retry;
2337 }
2338 else {
2339 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2340 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002344 } /* neither "nameserver" nor "resolvers" */
2345 else if (*args[0] != 0) {
2346 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350
2351 out:
2352 free(errmsg);
2353 return err_code;
2354}
Simon Horman0d16a402015-01-30 11:22:58 +09002355
2356/*
William Lallemand51097192015-04-14 16:35:22 +02002357 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002358 * Returns the error code, 0 if OK, or any combination of :
2359 * - ERR_ABORT: must abort ASAP
2360 * - ERR_FATAL: we can continue parsing but not start the service
2361 * - ERR_WARN: a warning has been emitted
2362 * - ERR_ALERT: an alert has been emitted
2363 * Only the two first ones can stop processing, the two others are just
2364 * indicators.
2365 */
2366int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2367{
2368 static struct mailers *curmailers = NULL;
2369 struct mailer *newmailer = NULL;
2370 const char *err;
2371 int err_code = 0;
2372 char *errmsg = NULL;
2373
2374 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2375 if (!*args[1]) {
2376 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2377 err_code |= ERR_ALERT | ERR_ABORT;
2378 goto out;
2379 }
2380
2381 err = invalid_char(args[1]);
2382 if (err) {
2383 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2384 file, linenum, *err, args[0], args[1]);
2385 err_code |= ERR_ALERT | ERR_ABORT;
2386 goto out;
2387 }
2388
2389 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2390 /*
2391 * If there are two proxies with the same name only following
2392 * combinations are allowed:
2393 */
2394 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002395 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 +09002396 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002398 }
2399 }
2400
Vincent Bernat02779b62016-04-03 13:48:43 +02002401 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2403 err_code |= ERR_ALERT | ERR_ABORT;
2404 goto out;
2405 }
2406
2407 curmailers->next = mailers;
2408 mailers = curmailers;
2409 curmailers->conf.file = strdup(file);
2410 curmailers->conf.line = linenum;
2411 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002412 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2413 * But need enough time so that timeouts don't occur
2414 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002415 }
2416 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2417 struct sockaddr_storage *sk;
2418 int port1, port2;
2419 struct protocol *proto;
2420
2421 if (!*args[2]) {
2422 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2423 file, linenum, args[0]);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
2426 }
2427
2428 err = invalid_char(args[1]);
2429 if (err) {
2430 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2431 file, linenum, *err, args[1]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
Vincent Bernat02779b62016-04-03 13:48:43 +02002436 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002437 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2438 err_code |= ERR_ALERT | ERR_ABORT;
2439 goto out;
2440 }
2441
2442 /* the mailers are linked backwards first */
2443 curmailers->count++;
2444 newmailer->next = curmailers->mailer_list;
2445 curmailers->mailer_list = newmailer;
2446 newmailer->mailers = curmailers;
2447 newmailer->conf.file = strdup(file);
2448 newmailer->conf.line = linenum;
2449
2450 newmailer->id = strdup(args[1]);
2451
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002452 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002453 if (!sk) {
2454 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458
2459 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002460 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2461 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002462 file, linenum, args[0], args[1]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
2467 if (port1 != port2) {
2468 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2469 file, linenum, args[0], args[1], args[2]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
2474 if (!port1) {
2475 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2476 file, linenum, args[0], args[1], args[2]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481 newmailer->addr = *sk;
2482 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002483 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002484 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002485 }
2486 else if (strcmp(args[0], "timeout") == 0) {
2487 if (!*args[1]) {
2488 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2489 file, linenum, args[0]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493 else if (strcmp(args[1], "mail") == 0) {
2494 const char *res;
2495 unsigned int timeout_mail;
2496 if (!*args[2]) {
2497 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2498 file, linenum, args[0], args[1]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2503 if (res) {
2504 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2505 file, linenum, *res, args[0]);
2506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
2508 }
2509 if (timeout_mail <= 0) {
2510 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 curmailers->timeout.mail = timeout_mail;
2515 } else {
2516 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2517 file, linenum, args[0], args[1]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 }
Simon Horman0d16a402015-01-30 11:22:58 +09002522 else if (*args[0] != 0) {
2523 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
2526 }
2527
2528out:
2529 free(errmsg);
2530 return err_code;
2531}
2532
Simon Horman9dc49962015-01-30 11:22:59 +09002533static void free_email_alert(struct proxy *p)
2534{
2535 free(p->email_alert.mailers.name);
2536 p->email_alert.mailers.name = NULL;
2537 free(p->email_alert.from);
2538 p->email_alert.from = NULL;
2539 free(p->email_alert.to);
2540 p->email_alert.to = NULL;
2541 free(p->email_alert.myhostname);
2542 p->email_alert.myhostname = NULL;
2543}
2544
Willy Tarreau3842f002009-06-14 11:39:52 +02002545int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546{
2547 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002548 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002549 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002550 int rc;
2551 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002552 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002553 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002554 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002555 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002556 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557
Willy Tarreau977b8e42006-12-29 14:19:17 +01002558 if (!strcmp(args[0], "listen"))
2559 rc = PR_CAP_LISTEN;
2560 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002561 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002562 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002563 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564 else
2565 rc = PR_CAP_NONE;
2566
2567 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 if (!*args[1]) {
2569 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002570 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_ABORT;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002575
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002576 err = invalid_char(args[1]);
2577 if (err) {
2578 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2579 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002581 }
2582
Willy Tarreau8f50b682015-05-26 11:45:02 +02002583 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2584 if (curproxy) {
2585 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2586 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2587 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002589 }
2590
Vincent Bernat02779b62016-04-03 13:48:43 +02002591 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_ABORT;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002596
Willy Tarreau97cb7802010-01-03 20:23:58 +01002597 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 curproxy->next = proxy;
2599 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002600 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2601 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002602 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002605 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606
William Lallemand6e62fb62015-04-28 16:55:23 +02002607 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2608 if (curproxy->cap & PR_CAP_FE)
2609 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
2612
2613 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002614 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002615 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002619 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002620 curproxy->no_options = defproxy.no_options;
2621 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002622 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002623 curproxy->except_net = defproxy.except_net;
2624 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002625 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002626 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002628 if (defproxy.fwdfor_hdr_len) {
2629 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2630 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2631 }
2632
Willy Tarreaub86db342009-11-30 11:50:16 +01002633 if (defproxy.orgto_hdr_len) {
2634 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2635 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2636 }
2637
Mark Lamourinec2247f02012-01-04 13:02:01 -05002638 if (defproxy.server_id_hdr_len) {
2639 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2640 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2641 }
2642
Willy Tarreau977b8e42006-12-29 14:19:17 +01002643 if (curproxy->cap & PR_CAP_FE) {
2644 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002645 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002646 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002647
2648 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002649 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2650 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651
2652 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654
Willy Tarreau977b8e42006-12-29 14:19:17 +01002655 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002656 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002657 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 curproxy->fullconn = defproxy.fullconn;
2659 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002660 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002661 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002663 if (defproxy.check_req) {
2664 curproxy->check_req = calloc(1, defproxy.check_len);
2665 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2666 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002667 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002669 if (defproxy.expect_str) {
2670 curproxy->expect_str = strdup(defproxy.expect_str);
2671 if (defproxy.expect_regex) {
2672 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002673 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2674 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002675 }
2676 }
2677
Willy Tarreau67402132012-05-31 20:40:20 +02002678 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (defproxy.cookie_name)
2680 curproxy->cookie_name = strdup(defproxy.cookie_name);
2681 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002682
2683 if (defproxy.dyncookie_key)
2684 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002685 if (defproxy.cookie_domain)
2686 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002687
Willy Tarreau31936852010-10-06 16:59:56 +02002688 if (defproxy.cookie_maxidle)
2689 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2690
2691 if (defproxy.cookie_maxlife)
2692 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2693
Emeric Brun647caf12009-06-30 17:57:00 +02002694 if (defproxy.rdp_cookie_name)
2695 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2696 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2697
Willy Tarreau01732802007-11-01 22:48:15 +01002698 if (defproxy.url_param_name)
2699 curproxy->url_param_name = strdup(defproxy.url_param_name);
2700 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002701
Benoitaffb4812009-03-25 13:02:10 +01002702 if (defproxy.hh_name)
2703 curproxy->hh_name = strdup(defproxy.hh_name);
2704 curproxy->hh_len = defproxy.hh_len;
2705 curproxy->hh_match_domain = defproxy.hh_match_domain;
2706
Willy Tarreauef9a3602012-12-08 22:29:20 +01002707 if (defproxy.conn_src.iface_name)
2708 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2709 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002710 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002711#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002712 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002713#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002714 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002717 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002718 if (defproxy.capture_name)
2719 curproxy->capture_name = strdup(defproxy.capture_name);
2720 curproxy->capture_namelen = defproxy.capture_namelen;
2721 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002725 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002726 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002727 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002728 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002729 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002730 curproxy->mon_net = defproxy.mon_net;
2731 curproxy->mon_mask = defproxy.mon_mask;
2732 if (defproxy.monitor_uri)
2733 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2734 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002735 if (defproxy.defbe.name)
2736 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002737
2738 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002739 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2740 if (curproxy->conf.logformat_string &&
2741 curproxy->conf.logformat_string != default_http_log_format &&
2742 curproxy->conf.logformat_string != default_tcp_log_format &&
2743 curproxy->conf.logformat_string != clf_http_log_format)
2744 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2745
2746 if (defproxy.conf.lfs_file) {
2747 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2748 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2749 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002750
2751 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2752 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2753 if (curproxy->conf.logformat_sd_string &&
2754 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2755 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2756
2757 if (defproxy.conf.lfsd_file) {
2758 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2759 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 }
2762
2763 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002764 curproxy->timeout.connect = defproxy.timeout.connect;
2765 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002766 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002767 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002768 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002769 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002770 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002771 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002772 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002773 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002774 }
2775
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002777 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002778
2779 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002780 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002781 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002782 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002783 LIST_INIT(&node->list);
2784 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2785 }
2786
Willy Tarreau62a61232013-04-12 18:13:46 +02002787 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2788 if (curproxy->conf.uniqueid_format_string)
2789 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2790
Dragan Dosen43885c72015-10-01 13:18:13 +02002791 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002792
Willy Tarreau62a61232013-04-12 18:13:46 +02002793 if (defproxy.conf.uif_file) {
2794 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2795 curproxy->conf.uif_line = defproxy.conf.uif_line;
2796 }
William Lallemanda73203e2012-03-12 12:48:57 +01002797
2798 /* copy default header unique id */
2799 if (defproxy.header_unique_id)
2800 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2801
William Lallemand82fe75c2012-10-23 10:25:10 +02002802 /* default compression options */
2803 if (defproxy.comp != NULL) {
2804 curproxy->comp = calloc(1, sizeof(struct comp));
2805 curproxy->comp->algos = defproxy.comp->algos;
2806 curproxy->comp->types = defproxy.comp->types;
2807 }
2808
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002810 curproxy->conf.used_listener_id = EB_ROOT;
2811 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002812
Simon Horman98637e52014-06-20 12:30:16 +09002813 if (defproxy.check_path)
2814 curproxy->check_path = strdup(defproxy.check_path);
2815 if (defproxy.check_command)
2816 curproxy->check_command = strdup(defproxy.check_command);
2817
Simon Horman9dc49962015-01-30 11:22:59 +09002818 if (defproxy.email_alert.mailers.name)
2819 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2820 if (defproxy.email_alert.from)
2821 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2822 if (defproxy.email_alert.to)
2823 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2824 if (defproxy.email_alert.myhostname)
2825 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002826 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002827 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002828
Willy Tarreau93893792009-07-23 13:19:11 +02002829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 }
2831 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2832 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002833 /* FIXME-20070101: we should do this too at the end of the
2834 * config parsing to free all default values.
2835 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002836 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2837 err_code |= ERR_ABORT;
2838 goto out;
2839 }
2840
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002842 free(defproxy.check_command);
2843 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002844 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002845 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002846 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002847 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002848 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002849 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002850 free(defproxy.capture_name);
2851 free(defproxy.monitor_uri);
2852 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002853 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002854 free(defproxy.fwdfor_hdr_name);
2855 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002856 free(defproxy.orgto_hdr_name);
2857 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002858 free(defproxy.server_id_hdr_name);
2859 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002860 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002861 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002862 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002863 free(defproxy.expect_regex);
2864 defproxy.expect_regex = NULL;
2865 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002866
Willy Tarreau62a61232013-04-12 18:13:46 +02002867 if (defproxy.conf.logformat_string != default_http_log_format &&
2868 defproxy.conf.logformat_string != default_tcp_log_format &&
2869 defproxy.conf.logformat_string != clf_http_log_format)
2870 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002871
Willy Tarreau62a61232013-04-12 18:13:46 +02002872 free(defproxy.conf.uniqueid_format_string);
2873 free(defproxy.conf.lfs_file);
2874 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002875 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002876 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002877
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002878 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2879 free(defproxy.conf.logformat_sd_string);
2880 free(defproxy.conf.lfsd_file);
2881
Willy Tarreaua534fea2008-08-03 12:19:50 +02002882 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002883 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002884
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 /* we cannot free uri_auth because it might already be used */
2886 init_default_instance();
2887 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002888 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2889 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002890 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 }
2893 else if (curproxy == NULL) {
2894 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002898
2899 /* update the current file and line being parsed */
2900 curproxy->conf.args.file = curproxy->conf.file;
2901 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902
2903 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002904 if (!strcmp(args[0], "server") ||
2905 !strcmp(args[0], "default-server") ||
2906 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002907 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2908 if (err_code & ERR_FATAL)
2909 goto out;
2910 }
2911 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002912 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002913 int cur_arg;
2914
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 if (curproxy == &defproxy) {
2916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922
Willy Tarreau24709282013-03-10 21:32:12 +01002923 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002924 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002929
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002930 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002931
2932 /* use default settings for unix sockets */
2933 bind_conf->ux.uid = global.unix_bind.ux.uid;
2934 bind_conf->ux.gid = global.unix_bind.ux.gid;
2935 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002936
2937 /* NOTE: the following line might create several listeners if there
2938 * are comma-separated IPs or port ranges. So all further processing
2939 * will have to be applied to all listeners created after last_listen.
2940 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002941 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2942 if (errmsg && *errmsg) {
2943 indent_msg(&errmsg, 2);
2944 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002945 }
2946 else
2947 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2948 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002952
Willy Tarreau4348fad2012-09-20 16:48:07 +02002953 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2954 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002955 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002956 }
2957
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002958 cur_arg = 2;
2959 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002960 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002961 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002962 char *err;
2963
Willy Tarreau26982662012-09-12 23:17:10 +02002964 kw = bind_find_kw(args[cur_arg]);
2965 if (kw) {
2966 char *err = NULL;
2967 int code;
2968
2969 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002970 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2971 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002972 cur_arg += 1 + kw->skip ;
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
2976
Willy Tarreau4348fad2012-09-20 16:48:07 +02002977 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002978 err_code |= code;
2979
2980 if (code) {
2981 if (err && *err) {
2982 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002983 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002984 }
2985 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002986 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2987 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002988 if (code & ERR_FATAL) {
2989 free(err);
2990 cur_arg += 1 + kw->skip;
2991 goto out;
2992 }
2993 }
2994 free(err);
2995 cur_arg += 1 + kw->skip;
2996 continue;
2997 }
2998
Willy Tarreau8638f482012-09-18 18:01:17 +02002999 err = NULL;
3000 if (!bind_dumped) {
3001 bind_dump_kws(&err);
3002 indent_msg(&err, 4);
3003 bind_dumped = 1;
3004 }
3005
3006 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3007 file, linenum, args[0], args[1], args[cur_arg],
3008 err ? " Registered keywords :" : "", err ? err : "");
3009 free(err);
3010
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003013 }
Willy Tarreau93893792009-07-23 13:19:11 +02003014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
3016 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003017 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 /* flush useless bits */
3027 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003030 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003031 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003033
William Lallemanddf1425a2015-04-28 20:17:49 +02003034 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3035 goto out;
3036
Willy Tarreau1c47f852006-07-09 08:22:27 +02003037 if (!*args[1]) {
3038 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3039 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003042 }
3043
Willy Tarreaua534fea2008-08-03 12:19:50 +02003044 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003045 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003046 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003047 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003048 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3049
Willy Tarreau93893792009-07-23 13:19:11 +02003050 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003053 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3054 goto out;
3055
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3057 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3058 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3059 else {
3060 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003066 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003067
3068 if (curproxy == &defproxy) {
3069 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003073 }
3074
William Lallemanddf1425a2015-04-28 20:17:49 +02003075 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3076 goto out;
3077
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003078 if (!*args[1]) {
3079 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003083 }
3084
3085 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003086 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003087 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003088
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003089 if (curproxy->uuid <= 0) {
3090 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003091 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003094 }
3095
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003096 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3097 if (node) {
3098 struct proxy *target = container_of(node, struct proxy, conf.id);
3099 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3100 file, linenum, proxy_type_str(curproxy), curproxy->id,
3101 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003106 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003107 else if (!strcmp(args[0], "description")) {
3108 int i, len=0;
3109 char *d;
3110
Cyril Bonté99ed3272010-01-24 23:29:44 +01003111 if (curproxy == &defproxy) {
3112 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3113 file, linenum, args[0]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003118 if (!*args[1]) {
3119 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3120 file, linenum, args[0]);
3121 return -1;
3122 }
3123
Willy Tarreau348acfe2014-04-14 15:00:39 +02003124 for (i = 1; *args[i]; i++)
3125 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003126
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003127 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003128 curproxy->desc = d;
3129
Willy Tarreau348acfe2014-04-14 15:00:39 +02003130 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3131 for (i = 2; *args[i]; i++)
3132 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003133
3134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003136 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 curproxy->state = PR_STSTOPPED;
3139 }
3140 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003141 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 curproxy->state = PR_STNEW;
3144 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003145 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3146 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003147 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003148
3149 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003150 unsigned int low, high;
3151
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003152 if (strcmp(args[cur_arg], "all") == 0) {
3153 set = 0;
3154 break;
3155 }
3156 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003157 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003158 }
3159 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003160 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003161 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003162 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003163 char *dash = strchr(args[cur_arg], '-');
3164
3165 low = high = str2uic(args[cur_arg]);
3166 if (dash)
3167 high = str2uic(dash + 1);
3168
3169 if (high < low) {
3170 unsigned int swap = low;
3171 low = high;
3172 high = swap;
3173 }
3174
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003175 if (low < 1 || high > LONGBITS) {
3176 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3177 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003180 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003181 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003182 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003183 }
3184 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003185 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3186 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003189 }
3190 cur_arg++;
3191 }
3192 curproxy->bind_proc = set;
3193 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003194 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003195 if (curproxy == &defproxy) {
3196 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003199 }
3200
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003201 err = invalid_char(args[1]);
3202 if (err) {
3203 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3204 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003206 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003207 }
3208
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003209 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003210 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3211 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003214 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003215 }
3216 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3217
3218 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3219 err_code |= ERR_WARN;
3220
3221 if (*(args[1]) == 0) {
3222 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3223 file, linenum, args[0]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227 free(curproxy->dyncookie_key);
3228 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3231 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232
Willy Tarreau977b8e42006-12-29 14:19:17 +01003233 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003235
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 if (*(args[1]) == 0) {
3237 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3238 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003242
Willy Tarreau67402132012-05-31 20:40:20 +02003243 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003244 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003245 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003246 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 curproxy->cookie_name = strdup(args[1]);
3248 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003249
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 cur_arg = 2;
3251 while (*(args[cur_arg])) {
3252 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003253 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 }
3255 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003256 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
3258 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003259 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003262 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
3264 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003265 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003267 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003268 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003271 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003273 else if (!strcmp(args[cur_arg], "httponly")) {
3274 curproxy->ck_opts |= PR_CK_HTTPONLY;
3275 }
3276 else if (!strcmp(args[cur_arg], "secure")) {
3277 curproxy->ck_opts |= PR_CK_SECURE;
3278 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003279 else if (!strcmp(args[cur_arg], "domain")) {
3280 if (!*args[cur_arg + 1]) {
3281 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3282 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003285 }
3286
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003287 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003288 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003289 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3290 " dots nor does not start with a dot."
3291 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003292 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003293 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003294 }
3295
3296 err = invalid_domainchar(args[cur_arg + 1]);
3297 if (err) {
3298 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3299 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003302 }
3303
Willy Tarreau68a897b2009-12-03 23:28:34 +01003304 if (!curproxy->cookie_domain) {
3305 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3306 } else {
3307 /* one domain was already specified, add another one by
3308 * building the string which will be returned along with
3309 * the cookie.
3310 */
3311 char *new_ptr;
3312 int new_len = strlen(curproxy->cookie_domain) +
3313 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3314 new_ptr = malloc(new_len);
3315 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3316 free(curproxy->cookie_domain);
3317 curproxy->cookie_domain = new_ptr;
3318 }
Willy Tarreau31936852010-10-06 16:59:56 +02003319 cur_arg++;
3320 }
3321 else if (!strcmp(args[cur_arg], "maxidle")) {
3322 unsigned int maxidle;
3323 const char *res;
3324
3325 if (!*args[cur_arg + 1]) {
3326 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3327 file, linenum, args[cur_arg]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331
3332 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3333 if (res) {
3334 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3335 file, linenum, *res, args[cur_arg]);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
3338 }
3339 curproxy->cookie_maxidle = maxidle;
3340 cur_arg++;
3341 }
3342 else if (!strcmp(args[cur_arg], "maxlife")) {
3343 unsigned int maxlife;
3344 const char *res;
3345
3346 if (!*args[cur_arg + 1]) {
3347 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3348 file, linenum, args[cur_arg]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352
3353 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3354 if (res) {
3355 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3356 file, linenum, *res, args[cur_arg]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003361 cur_arg++;
3362 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003363 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003364
3365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3366 err_code |= ERR_WARN;
3367 curproxy->ck_opts |= PR_CK_DYNAMIC;
3368 }
3369
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003371 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 +02003372 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376 cur_arg++;
3377 }
Willy Tarreau67402132012-05-31 20:40:20 +02003378 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3380 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383
Willy Tarreau67402132012-05-31 20:40:20 +02003384 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003389
Willy Tarreau67402132012-05-31 20:40:20 +02003390 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003391 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3392 file, linenum);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003396 else if (!strcmp(args[0], "email-alert")) {
3397 if (*(args[1]) == 0) {
3398 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3399 file, linenum, args[0]);
3400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
3402 }
3403
3404 if (!strcmp(args[1], "from")) {
3405 if (*(args[1]) == 0) {
3406 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3407 file, linenum, args[1]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411 free(curproxy->email_alert.from);
3412 curproxy->email_alert.from = strdup(args[2]);
3413 }
3414 else if (!strcmp(args[1], "mailers")) {
3415 if (*(args[1]) == 0) {
3416 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3417 file, linenum, args[1]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421 free(curproxy->email_alert.mailers.name);
3422 curproxy->email_alert.mailers.name = strdup(args[2]);
3423 }
3424 else if (!strcmp(args[1], "myhostname")) {
3425 if (*(args[1]) == 0) {
3426 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3427 file, linenum, args[1]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431 free(curproxy->email_alert.myhostname);
3432 curproxy->email_alert.myhostname = strdup(args[2]);
3433 }
Simon Horman64e34162015-02-06 11:11:57 +09003434 else if (!strcmp(args[1], "level")) {
3435 curproxy->email_alert.level = get_log_level(args[2]);
3436 if (curproxy->email_alert.level < 0) {
3437 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3438 file, linenum, args[1], args[2]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 }
Simon Horman9dc49962015-01-30 11:22:59 +09003443 else if (!strcmp(args[1], "to")) {
3444 if (*(args[1]) == 0) {
3445 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3446 file, linenum, args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
3450 free(curproxy->email_alert.to);
3451 curproxy->email_alert.to = strdup(args[2]);
3452 }
3453 else {
3454 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3455 file, linenum, args[1]);
3456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
3458 }
Simon Horman64e34162015-02-06 11:11:57 +09003459 /* Indicate that the email_alert is at least partially configured */
3460 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003461 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003462 else if (!strcmp(args[0], "external-check")) {
3463 if (*(args[1]) == 0) {
3464 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3465 file, linenum, args[0]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469
3470 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003471 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003472 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003473 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003474 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3475 file, linenum, args[1]);
3476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
3478 }
3479 free(curproxy->check_command);
3480 curproxy->check_command = strdup(args[2]);
3481 }
3482 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003483 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003484 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003485 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003486 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3487 file, linenum, args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 free(curproxy->check_path);
3492 curproxy->check_path = strdup(args[2]);
3493 }
3494 else {
3495 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3496 file, linenum, args[1]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003501 else if (!strcmp(args[0], "persist")) { /* persist */
3502 if (*(args[1]) == 0) {
3503 Alert("parsing [%s:%d] : missing persist method.\n",
3504 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003507 }
3508
3509 if (!strncmp(args[1], "rdp-cookie", 10)) {
3510 curproxy->options2 |= PR_O2_RDPC_PRST;
3511
Emeric Brunb982a3d2010-01-04 15:45:53 +01003512 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003513 const char *beg, *end;
3514
3515 beg = args[1] + 11;
3516 end = strchr(beg, ')');
3517
William Lallemanddf1425a2015-04-28 20:17:49 +02003518 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3519 goto out;
3520
Emeric Brun647caf12009-06-30 17:57:00 +02003521 if (!end || end == beg) {
3522 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003526 }
3527
3528 free(curproxy->rdp_cookie_name);
3529 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3530 curproxy->rdp_cookie_len = end-beg;
3531 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003532 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003533 free(curproxy->rdp_cookie_name);
3534 curproxy->rdp_cookie_name = strdup("msts");
3535 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3536 }
3537 else { /* syntax */
3538 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3539 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003542 }
3543 }
3544 else {
3545 Alert("parsing [%s:%d] : unknown persist method.\n",
3546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003549 }
3550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003552 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003556 else if (!strcmp(args[0], "load-server-state-from-file")) {
3557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3558 err_code |= ERR_WARN;
3559 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3560 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3561 }
3562 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3563 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3564 }
3565 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3566 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3567 }
3568 else {
3569 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3570 file, linenum, args[0], args[1]);
3571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
3573 }
3574 }
3575 else if (!strcmp(args[0], "server-state-file-name")) {
3576 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3577 err_code |= ERR_WARN;
3578 if (*(args[1]) == 0) {
3579 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3580 file, linenum, args[0]);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583 }
3584 else if (!strcmp(args[1], "use-backend-name"))
3585 curproxy->server_state_file_name = strdup(curproxy->id);
3586 else
3587 curproxy->server_state_file_name = strdup(args[1]);
3588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003590 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003592
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003594 if (curproxy == &defproxy) {
3595 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599
William Lallemand1a748ae2015-05-19 16:37:23 +02003600 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3601 goto out;
3602
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 if (*(args[4]) == 0) {
3604 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003609 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 curproxy->capture_name = strdup(args[2]);
3611 curproxy->capture_namelen = strlen(curproxy->capture_name);
3612 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 curproxy->to_log |= LW_COOKIE;
3614 }
3615 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3616 struct cap_hdr *hdr;
3617
3618 if (curproxy == &defproxy) {
3619 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 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623
William Lallemand1a748ae2015-05-19 16:37:23 +02003624 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3625 goto out;
3626
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3628 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3629 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 }
3633
Vincent Bernat02779b62016-04-03 13:48:43 +02003634 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 hdr->next = curproxy->req_cap;
3636 hdr->name = strdup(args[3]);
3637 hdr->namelen = strlen(args[3]);
3638 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003639 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 hdr->index = curproxy->nb_req_cap++;
3641 curproxy->req_cap = hdr;
3642 curproxy->to_log |= LW_REQHDR;
3643 }
3644 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3645 struct cap_hdr *hdr;
3646
3647 if (curproxy == &defproxy) {
3648 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 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652
William Lallemand1a748ae2015-05-19 16:37:23 +02003653 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3654 goto out;
3655
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3657 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3658 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003662 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 hdr->next = curproxy->rsp_cap;
3664 hdr->name = strdup(args[3]);
3665 hdr->namelen = strlen(args[3]);
3666 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003667 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 hdr->index = curproxy->nb_rsp_cap++;
3669 curproxy->rsp_cap = hdr;
3670 curproxy->to_log |= LW_RSPHDR;
3671 }
3672 else {
3673 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003680 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003682
William Lallemanddf1425a2015-04-28 20:17:49 +02003683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3684 goto out;
3685
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 if (*(args[1]) == 0) {
3687 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\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 curproxy->conn_retries = atol(args[1]);
3693 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003694 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003695 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003696
3697 if (curproxy == &defproxy) {
3698 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
3701 }
3702
Willy Tarreau20b0de52012-12-24 15:45:22 +01003703 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003704 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003705 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3706 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3707 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3708 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003709 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 +01003710 file, linenum, args[0]);
3711 err_code |= ERR_WARN;
3712 }
3713
Willy Tarreauff011f22011-01-06 17:51:27 +01003714 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003715
Willy Tarreauff011f22011-01-06 17:51:27 +01003716 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003717 err_code |= ERR_ALERT | ERR_ABORT;
3718 goto out;
3719 }
3720
Willy Tarreau5002f572014-04-23 01:32:02 +02003721 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003722 err_code |= warnif_cond_conflicts(rule->cond,
3723 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3724 file, linenum);
3725
Willy Tarreauff011f22011-01-06 17:51:27 +01003726 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003727 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003728 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003729 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003730
3731 if (curproxy == &defproxy) {
3732 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736
3737 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003738 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003739 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3740 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003741 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3742 file, linenum, args[0]);
3743 err_code |= ERR_WARN;
3744 }
3745
3746 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3747
3748 if (!rule) {
3749 err_code |= ERR_ALERT | ERR_ABORT;
3750 goto out;
3751 }
3752
3753 err_code |= warnif_cond_conflicts(rule->cond,
3754 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3755 file, linenum);
3756
3757 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3758 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003759 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3760 /* set the header name and length into the proxy structure */
3761 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3762 err_code |= ERR_WARN;
3763
3764 if (!*args[1]) {
3765 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3766 file, linenum, args[0]);
3767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
3769 }
3770
3771 /* set the desired header name */
3772 free(curproxy->server_id_hdr_name);
3773 curproxy->server_id_hdr_name = strdup(args[1]);
3774 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3775 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003776 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003777 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003778
Willy Tarreaub099aca2008-10-12 17:26:37 +02003779 if (curproxy == &defproxy) {
3780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003783 }
3784
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003785 /* emulate "block" using "http-request block". Since these rules are supposed to
3786 * be processed before all http-request rules, we put them into their own list
3787 * and will insert them at the end.
3788 */
3789 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3790 if (!rule) {
3791 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003792 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003793 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003794 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3795 err_code |= warnif_cond_conflicts(rule->cond,
3796 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3797 file, linenum);
3798 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003799
3800 if (!already_warned(WARN_BLOCK_DEPRECATED))
3801 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]);
3802
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003803 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003804 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003805 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003806
Cyril Bonté99ed3272010-01-24 23:29:44 +01003807 if (curproxy == &defproxy) {
3808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812
Willy Tarreaube4653b2015-05-28 15:26:58 +02003813 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003814 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3815 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003818 }
3819
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003820 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003821 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003822 err_code |= warnif_cond_conflicts(rule->cond,
3823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3824 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003825 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003826 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003827 struct switching_rule *rule;
3828
Willy Tarreaub099aca2008-10-12 17:26:37 +02003829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003833 }
3834
Willy Tarreau55ea7572007-06-17 19:56:27 +02003835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003837
3838 if (*(args[1]) == 0) {
3839 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003842 }
3843
Willy Tarreauf51658d2014-04-23 01:21:56 +02003844 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3845 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3846 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3847 file, linenum, errmsg);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851
Willy Tarreauf51658d2014-04-23 01:21:56 +02003852 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003853 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003854 else if (*args[2]) {
3855 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3856 file, linenum, args[2]);
3857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
3859 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003860
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003861 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003862 if (!rule) {
3863 Alert("Out of memory error.\n");
3864 goto out;
3865 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003866 rule->cond = cond;
3867 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003868 rule->line = linenum;
3869 rule->file = strdup(file);
3870 if (!rule->file) {
3871 Alert("Out of memory error.\n");
3872 goto out;
3873 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003874 LIST_INIT(&rule->list);
3875 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3876 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003877 else if (strcmp(args[0], "use-server") == 0) {
3878 struct server_rule *rule;
3879
3880 if (curproxy == &defproxy) {
3881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
3886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3887 err_code |= ERR_WARN;
3888
3889 if (*(args[1]) == 0) {
3890 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894
3895 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3896 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3897 file, linenum, args[0]);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003902 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3903 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3904 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
3907 }
3908
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003909 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003910
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003911 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003912 rule->cond = cond;
3913 rule->srv.name = strdup(args[1]);
3914 LIST_INIT(&rule->list);
3915 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3916 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3917 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003918 else if ((!strcmp(args[0], "force-persist")) ||
3919 (!strcmp(args[0], "ignore-persist"))) {
3920 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003921
3922 if (curproxy == &defproxy) {
3923 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
3928 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3929 err_code |= ERR_WARN;
3930
Willy Tarreauef6494c2010-01-28 17:12:36 +01003931 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003932 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3933 file, linenum, args[0]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
3937
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003938 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3939 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3940 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
3943 }
3944
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003945 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3946 * where force-persist is applied.
3947 */
3948 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003949
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003950 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003951 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003952 if (!strcmp(args[0], "force-persist")) {
3953 rule->type = PERSIST_TYPE_FORCE;
3954 } else {
3955 rule->type = PERSIST_TYPE_IGNORE;
3956 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003957 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003958 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003959 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003960 else if (!strcmp(args[0], "stick-table")) {
3961 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003962 struct proxy *other;
3963
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003964 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003965 if (other) {
3966 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3967 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003971
Emeric Brun32da3c42010-09-23 18:39:19 +02003972 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003973 curproxy->table.type = (unsigned int)-1;
3974 while (*args[myidx]) {
3975 const char *err;
3976
3977 if (strcmp(args[myidx], "size") == 0) {
3978 myidx++;
3979 if (!*(args[myidx])) {
3980 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3981 file, linenum, args[myidx-1]);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
3985 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3986 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3987 file, linenum, *err, args[myidx-1]);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003991 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003992 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003993 else if (strcmp(args[myidx], "peers") == 0) {
3994 myidx++;
Godbach50523162013-12-11 19:48:57 +08003995 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003996 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3997 file, linenum, args[myidx-1]);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Godbach50523162013-12-11 19:48:57 +08004000 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004001 curproxy->table.peers.name = strdup(args[myidx++]);
4002 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004003 else if (strcmp(args[myidx], "expire") == 0) {
4004 myidx++;
4005 if (!*(args[myidx])) {
4006 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4007 file, linenum, args[myidx-1]);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4012 if (err) {
4013 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4014 file, linenum, *err, args[myidx-1]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004018 if (val > INT_MAX) {
4019 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4020 file, linenum, val);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004024 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004025 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004026 }
4027 else if (strcmp(args[myidx], "nopurge") == 0) {
4028 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004029 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004030 }
4031 else if (strcmp(args[myidx], "type") == 0) {
4032 myidx++;
4033 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4034 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4035 file, linenum, args[myidx]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004039 /* myidx already points to next arg */
4040 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004041 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004042 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004043 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004044
4045 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004046 nw = args[myidx];
4047 while (*nw) {
4048 /* the "store" keyword supports a comma-separated list */
4049 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004050 sa = NULL; /* store arg */
4051 while (*nw && *nw != ',') {
4052 if (*nw == '(') {
4053 *nw = 0;
4054 sa = ++nw;
4055 while (*nw != ')') {
4056 if (!*nw) {
4057 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4058 file, linenum, args[0], cw);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062 nw++;
4063 }
4064 *nw = '\0';
4065 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004066 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004067 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004068 if (*nw)
4069 *nw++ = '\0';
4070 type = stktable_get_data_type(cw);
4071 if (type < 0) {
4072 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4073 file, linenum, args[0], cw);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
Willy Tarreauac782882010-06-20 10:41:54 +02004077
4078 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4079 switch (err) {
4080 case PE_NONE: break;
4081 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004082 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4083 file, linenum, args[0], cw);
4084 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004085 break;
4086
4087 case PE_ARG_MISSING:
4088 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4089 file, linenum, args[0], cw);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092
4093 case PE_ARG_NOT_USED:
4094 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4095 file, linenum, args[0], cw);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098
4099 default:
4100 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4101 file, linenum, args[0], cw);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004104 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004105 }
4106 myidx++;
4107 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004108 else {
4109 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4110 file, linenum, args[myidx]);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 }
4115
4116 if (!curproxy->table.size) {
4117 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4118 file, linenum);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
4122
4123 if (curproxy->table.type == (unsigned int)-1) {
4124 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4125 file, linenum);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 }
4130 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004132 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 int myidx = 0;
4134 const char *name = NULL;
4135 int flags;
4136
4137 if (curproxy == &defproxy) {
4138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
4141 }
4142
4143 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4144 err_code |= ERR_WARN;
4145 goto out;
4146 }
4147
4148 myidx++;
4149 if ((strcmp(args[myidx], "store") == 0) ||
4150 (strcmp(args[myidx], "store-request") == 0)) {
4151 myidx++;
4152 flags = STK_IS_STORE;
4153 }
4154 else if (strcmp(args[myidx], "store-response") == 0) {
4155 myidx++;
4156 flags = STK_IS_STORE | STK_ON_RSP;
4157 }
4158 else if (strcmp(args[myidx], "match") == 0) {
4159 myidx++;
4160 flags = STK_IS_MATCH;
4161 }
4162 else if (strcmp(args[myidx], "on") == 0) {
4163 myidx++;
4164 flags = STK_IS_MATCH | STK_IS_STORE;
4165 }
4166 else {
4167 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
4172 if (*(args[myidx]) == 0) {
4173 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004178 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004179 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004180 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004181 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
4186 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004187 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4188 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4189 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004190 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004191 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004192 goto out;
4193 }
4194 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004195 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4196 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4197 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004198 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004199 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004200 goto out;
4201 }
4202 }
4203
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004204 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004205 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004206
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 if (strcmp(args[myidx], "table") == 0) {
4208 myidx++;
4209 name = args[myidx++];
4210 }
4211
Willy Tarreauef6494c2010-01-28 17:12:36 +01004212 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004213 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4214 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4215 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004216 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004217 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004218 goto out;
4219 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004220 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004221 else if (*(args[myidx])) {
4222 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4223 file, linenum, args[0], args[myidx]);
4224 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004225 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004226 goto out;
4227 }
Emeric Brun97679e72010-09-23 17:56:44 +02004228 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004229 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004230 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004231 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004232
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004233 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004234 rule->cond = cond;
4235 rule->expr = expr;
4236 rule->flags = flags;
4237 rule->table.name = name ? strdup(name) : NULL;
4238 LIST_INIT(&rule->list);
4239 if (flags & STK_ON_RSP)
4240 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4241 else
4242 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 else if (!strcmp(args[0], "stats")) {
4245 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4246 curproxy->uri_auth = NULL; /* we must detach from the default config */
4247
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004248 if (!*args[1]) {
4249 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004250 } else if (!strcmp(args[1], "admin")) {
4251 struct stats_admin_rule *rule;
4252
4253 if (curproxy == &defproxy) {
4254 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4260 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4261 err_code |= ERR_ALERT | ERR_ABORT;
4262 goto out;
4263 }
4264
4265 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4266 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4267 file, linenum, args[0], args[1]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004271 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4272 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4273 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
4277
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004278 err_code |= warnif_cond_conflicts(cond,
4279 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4280 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004281
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004282 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004283 rule->cond = cond;
4284 LIST_INIT(&rule->list);
4285 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 } else if (!strcmp(args[1], "uri")) {
4287 if (*(args[2]) == 0) {
4288 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_ABORT;
4294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 }
4296 } else if (!strcmp(args[1], "realm")) {
4297 if (*(args[2]) == 0) {
4298 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4302 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_ABORT;
4304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004306 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004307 unsigned interval;
4308
4309 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4310 if (err) {
4311 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4312 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004315 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02004319 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004320 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004321 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004322
4323 if (curproxy == &defproxy) {
4324 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328
4329 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4330 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4331 err_code |= ERR_ALERT | ERR_ABORT;
4332 goto out;
4333 }
4334
Willy Tarreauff011f22011-01-06 17:51:27 +01004335 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004336 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004337 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4338 file, linenum, args[0]);
4339 err_code |= ERR_WARN;
4340 }
4341
Willy Tarreauff011f22011-01-06 17:51:27 +01004342 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004343
Willy Tarreauff011f22011-01-06 17:51:27 +01004344 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004345 err_code |= ERR_ALERT | ERR_ABORT;
4346 goto out;
4347 }
4348
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004349 err_code |= warnif_cond_conflicts(rule->cond,
4350 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4351 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004352 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004353
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354 } else if (!strcmp(args[1], "auth")) {
4355 if (*(args[2]) == 0) {
4356 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_ABORT;
4362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
4364 } else if (!strcmp(args[1], "scope")) {
4365 if (*(args[2]) == 0) {
4366 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4370 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_ABORT;
4372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 }
4374 } else if (!strcmp(args[1], "enable")) {
4375 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4376 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_ABORT;
4378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004379 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004380 } else if (!strcmp(args[1], "hide-version")) {
4381 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4382 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_ABORT;
4384 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004385 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004386 } else if (!strcmp(args[1], "show-legends")) {
4387 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4388 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4389 err_code |= ERR_ALERT | ERR_ABORT;
4390 goto out;
4391 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004392 } else if (!strcmp(args[1], "show-node")) {
4393
4394 if (*args[2]) {
4395 int i;
4396 char c;
4397
4398 for (i=0; args[2][i]; i++) {
4399 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004400 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4401 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004402 break;
4403 }
4404
4405 if (!i || args[2][i]) {
4406 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4407 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4408 file, linenum, args[0], args[1]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
4412 }
4413
4414 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4415 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4416 err_code |= ERR_ALERT | ERR_ABORT;
4417 goto out;
4418 }
4419 } else if (!strcmp(args[1], "show-desc")) {
4420 char *desc = NULL;
4421
4422 if (*args[2]) {
4423 int i, len=0;
4424 char *d;
4425
Willy Tarreau348acfe2014-04-14 15:00:39 +02004426 for (i = 2; *args[i]; i++)
4427 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004428
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004429 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004430
Willy Tarreau348acfe2014-04-14 15:00:39 +02004431 d += snprintf(d, desc + len - d, "%s", args[2]);
4432 for (i = 3; *args[i]; i++)
4433 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004434 }
4435
4436 if (!*args[2] && !global.desc)
4437 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4438 file, linenum, args[1]);
4439 else {
4440 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4441 free(desc);
4442 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4443 err_code |= ERR_ALERT | ERR_ABORT;
4444 goto out;
4445 }
4446 free(desc);
4447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004449stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004450 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 +01004451 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
4455 }
4456 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004457 int optnum;
4458
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004459 if (*(args[1]) == '\0') {
4460 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004465
4466 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4467 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004468 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4469 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4470 file, linenum, cfg_opts[optnum].name);
4471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
4473 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004474 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4475 goto out;
4476
Willy Tarreau93893792009-07-23 13:19:11 +02004477 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4478 err_code |= ERR_WARN;
4479 goto out;
4480 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004481
Willy Tarreau3842f002009-06-14 11:39:52 +02004482 curproxy->no_options &= ~cfg_opts[optnum].val;
4483 curproxy->options &= ~cfg_opts[optnum].val;
4484
4485 switch (kwm) {
4486 case KWM_STD:
4487 curproxy->options |= cfg_opts[optnum].val;
4488 break;
4489 case KWM_NO:
4490 curproxy->no_options |= cfg_opts[optnum].val;
4491 break;
4492 case KWM_DEF: /* already cleared */
4493 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004494 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004495
Willy Tarreau93893792009-07-23 13:19:11 +02004496 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004497 }
4498 }
4499
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004500 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4501 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004502 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4503 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4504 file, linenum, cfg_opts2[optnum].name);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004508 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4509 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004510 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4511 err_code |= ERR_WARN;
4512 goto out;
4513 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004514
Willy Tarreau3842f002009-06-14 11:39:52 +02004515 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4516 curproxy->options2 &= ~cfg_opts2[optnum].val;
4517
4518 switch (kwm) {
4519 case KWM_STD:
4520 curproxy->options2 |= cfg_opts2[optnum].val;
4521 break;
4522 case KWM_NO:
4523 curproxy->no_options2 |= cfg_opts2[optnum].val;
4524 break;
4525 case KWM_DEF: /* already cleared */
4526 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004527 }
Willy Tarreau93893792009-07-23 13:19:11 +02004528 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004529 }
4530 }
4531
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004532 /* HTTP options override each other. They can be cancelled using
4533 * "no option xxx" which only switches to default mode if the mode
4534 * was this one (useful for cancelling options set in defaults
4535 * sections).
4536 */
4537 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004538 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4539 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004540 if (kwm == KWM_STD) {
4541 curproxy->options &= ~PR_O_HTTP_MODE;
4542 curproxy->options |= PR_O_HTTP_PCL;
4543 goto out;
4544 }
4545 else if (kwm == KWM_NO) {
4546 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4547 curproxy->options &= ~PR_O_HTTP_MODE;
4548 goto out;
4549 }
4550 }
4551 else if (strcmp(args[1], "forceclose") == 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_FCL;
4557 goto out;
4558 }
4559 else if (kwm == KWM_NO) {
4560 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4561 curproxy->options &= ~PR_O_HTTP_MODE;
4562 goto out;
4563 }
4564 }
4565 else if (strcmp(args[1], "http-server-close") == 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_SCL;
4571 goto out;
4572 }
4573 else if (kwm == KWM_NO) {
4574 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4575 curproxy->options &= ~PR_O_HTTP_MODE;
4576 goto out;
4577 }
4578 }
4579 else if (strcmp(args[1], "http-keep-alive") == 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_KAL;
4585 goto out;
4586 }
4587 else if (kwm == KWM_NO) {
4588 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4589 curproxy->options &= ~PR_O_HTTP_MODE;
4590 goto out;
4591 }
4592 }
4593 else if (strcmp(args[1], "http-tunnel") == 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_TUN;
4599 goto out;
4600 }
4601 else if (kwm == KWM_NO) {
4602 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4603 curproxy->options &= ~PR_O_HTTP_MODE;
4604 goto out;
4605 }
4606 }
4607
Joseph Lynch726ab712015-05-11 23:25:34 -07004608 /* Redispatch can take an integer argument that control when the
4609 * resispatch occurs. All values are relative to the retries option.
4610 * This can be cancelled using "no option xxx".
4611 */
4612 if (strcmp(args[1], "redispatch") == 0) {
4613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4614 err_code |= ERR_WARN;
4615 goto out;
4616 }
4617
4618 curproxy->no_options &= ~PR_O_REDISP;
4619 curproxy->options &= ~PR_O_REDISP;
4620
4621 switch (kwm) {
4622 case KWM_STD:
4623 curproxy->options |= PR_O_REDISP;
4624 curproxy->redispatch_after = -1;
4625 if(*args[2]) {
4626 curproxy->redispatch_after = atol(args[2]);
4627 }
4628 break;
4629 case KWM_NO:
4630 curproxy->no_options |= PR_O_REDISP;
4631 curproxy->redispatch_after = 0;
4632 break;
4633 case KWM_DEF: /* already cleared */
4634 break;
4635 }
4636 goto out;
4637 }
4638
Willy Tarreau3842f002009-06-14 11:39:52 +02004639 if (kwm != KWM_STD) {
4640 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004641 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004644 }
4645
Emeric Brun3a058f32009-06-30 18:26:00 +02004646 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004647 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004649 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004650 if (*(args[2]) != '\0') {
4651 if (!strcmp(args[2], "clf")) {
4652 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004653 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004654 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004655 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004658 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004659 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4660 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004661 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004662 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4663 char *oldlogformat = "log-format";
4664 char *clflogformat = "";
4665
4666 if (curproxy->conf.logformat_string == default_http_log_format)
4667 oldlogformat = "option httplog";
4668 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4669 oldlogformat = "option tcplog";
4670 else if (curproxy->conf.logformat_string == clf_http_log_format)
4671 oldlogformat = "option httplog clf";
4672 if (logformat == clf_http_log_format)
4673 clflogformat = " clf";
4674 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4675 file, linenum, clflogformat, oldlogformat);
4676 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004677 if (curproxy->conf.logformat_string != default_http_log_format &&
4678 curproxy->conf.logformat_string != default_tcp_log_format &&
4679 curproxy->conf.logformat_string != clf_http_log_format)
4680 free(curproxy->conf.logformat_string);
4681 curproxy->conf.logformat_string = logformat;
4682
4683 free(curproxy->conf.lfs_file);
4684 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4685 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004686 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004687 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004688 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4689 char *oldlogformat = "log-format";
4690
4691 if (curproxy->conf.logformat_string == default_http_log_format)
4692 oldlogformat = "option httplog";
4693 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4694 oldlogformat = "option tcplog";
4695 else if (curproxy->conf.logformat_string == clf_http_log_format)
4696 oldlogformat = "option httplog clf";
4697 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4698 file, linenum, oldlogformat);
4699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004701 if (curproxy->conf.logformat_string != default_http_log_format &&
4702 curproxy->conf.logformat_string != default_tcp_log_format &&
4703 curproxy->conf.logformat_string != clf_http_log_format)
4704 free(curproxy->conf.logformat_string);
4705 curproxy->conf.logformat_string = default_tcp_log_format;
4706
4707 free(curproxy->conf.lfs_file);
4708 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4709 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004710
4711 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4712 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004715 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004716 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004717 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004718
William Lallemanddf1425a2015-04-28 20:17:49 +02004719 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4720 goto out;
4721
Willy Tarreau13943ab2006-12-31 00:24:10 +01004722 if (curproxy->cap & PR_CAP_FE)
4723 curproxy->options |= PR_O_TCP_CLI_KA;
4724 if (curproxy->cap & PR_CAP_BE)
4725 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004726 }
4727 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004729 err_code |= ERR_WARN;
4730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004732 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004733 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004734 curproxy->options2 &= ~PR_O2_CHK_ANY;
4735 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 if (!*args[2]) { /* no argument */
4737 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4738 curproxy->check_len = strlen(DEF_CHECK_REQ);
4739 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004740 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004741 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004743 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004745 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 if (*args[4])
4747 reqlen += strlen(args[4]);
4748 else
4749 reqlen += strlen("HTTP/1.0");
4750
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004751 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004753 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004755 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4756 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004757 }
4758 else if (!strcmp(args[1], "ssl-hello-chk")) {
4759 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004762
Willy Tarreaua534fea2008-08-03 12:19:50 +02004763 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004764 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004765 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004766 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004767
4768 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
Willy Tarreau23677902007-05-08 23:50:35 +02004771 else if (!strcmp(args[1], "smtpchk")) {
4772 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004773 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004774 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004775 curproxy->options2 &= ~PR_O2_CHK_ANY;
4776 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004777
4778 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4779 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4780 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4781 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4782 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4783 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004784 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004785 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4786 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4787 } else {
4788 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4789 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4790 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4791 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4792 }
4793 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004794 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4795 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004796 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004797 else if (!strcmp(args[1], "pgsql-check")) {
4798 /* use PostgreSQL request to check servers' health */
4799 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4800 err_code |= ERR_WARN;
4801
4802 free(curproxy->check_req);
4803 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004804 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004805 curproxy->options2 |= PR_O2_PGSQL_CHK;
4806
4807 if (*(args[2])) {
4808 int cur_arg = 2;
4809
4810 while (*(args[cur_arg])) {
4811 if (strcmp(args[cur_arg], "user") == 0) {
4812 char * packet;
4813 uint32_t packet_len;
4814 uint32_t pv;
4815
4816 /* suboption header - needs additional argument for it */
4817 if (*(args[cur_arg+1]) == 0) {
4818 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4819 file, linenum, args[0], args[1], args[cur_arg]);
4820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
4823
4824 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4825 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4826 pv = htonl(0x30000); /* protocol version 3.0 */
4827
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004828 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004829
4830 memcpy(packet + 4, &pv, 4);
4831
4832 /* copy "user" */
4833 memcpy(packet + 8, "user", 4);
4834
4835 /* copy username */
4836 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4837
4838 free(curproxy->check_req);
4839 curproxy->check_req = packet;
4840 curproxy->check_len = packet_len;
4841
4842 packet_len = htonl(packet_len);
4843 memcpy(packet, &packet_len, 4);
4844 cur_arg += 2;
4845 } else {
4846 /* unknown suboption - catchall */
4847 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4848 file, linenum, args[0], args[1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852 } /* end while loop */
4853 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004854 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4855 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004856 }
4857
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004858 else if (!strcmp(args[1], "redis-check")) {
4859 /* use REDIS PING request to check servers' health */
4860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4861 err_code |= ERR_WARN;
4862
4863 free(curproxy->check_req);
4864 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004865 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004866 curproxy->options2 |= PR_O2_REDIS_CHK;
4867
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004868 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004869 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4870 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004871
4872 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4873 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004874 }
4875
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004876 else if (!strcmp(args[1], "mysql-check")) {
4877 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004878 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4879 err_code |= ERR_WARN;
4880
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004881 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004882 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004883 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004884 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004885
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004886 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004887 * const char mysql40_client_auth_pkt[] = {
4888 * "\x0e\x00\x00" // packet length
4889 * "\x01" // packet number
4890 * "\x00\x00" // client capabilities
4891 * "\x00\x00\x01" // max packet
4892 * "haproxy\x00" // username (null terminated string)
4893 * "\x00" // filler (always 0x00)
4894 * "\x01\x00\x00" // packet length
4895 * "\x00" // packet number
4896 * "\x01" // COM_QUIT command
4897 * };
4898 */
4899
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004900 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4901 * const char mysql41_client_auth_pkt[] = {
4902 * "\x0e\x00\x00\" // packet length
4903 * "\x01" // packet number
4904 * "\x00\x00\x00\x00" // client capabilities
4905 * "\x00\x00\x00\x01" // max packet
4906 * "\x21" // character set (UTF-8)
4907 * char[23] // All zeroes
4908 * "haproxy\x00" // username (null terminated string)
4909 * "\x00" // filler (always 0x00)
4910 * "\x01\x00\x00" // packet length
4911 * "\x00" // packet number
4912 * "\x01" // COM_QUIT command
4913 * };
4914 */
4915
4916
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004917 if (*(args[2])) {
4918 int cur_arg = 2;
4919
4920 while (*(args[cur_arg])) {
4921 if (strcmp(args[cur_arg], "user") == 0) {
4922 char *mysqluser;
4923 int packetlen, reqlen, userlen;
4924
4925 /* suboption header - needs additional argument for it */
4926 if (*(args[cur_arg+1]) == 0) {
4927 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4928 file, linenum, args[0], args[1], args[cur_arg]);
4929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931 }
4932 mysqluser = args[cur_arg + 1];
4933 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004934
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004935 if (*(args[cur_arg+2])) {
4936 if (!strcmp(args[cur_arg+2], "post-41")) {
4937 packetlen = userlen + 7 + 27;
4938 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004939
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004940 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004941 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004942 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004943
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004944 snprintf(curproxy->check_req, 4, "%c%c%c",
4945 ((unsigned char) packetlen & 0xff),
4946 ((unsigned char) (packetlen >> 8) & 0xff),
4947 ((unsigned char) (packetlen >> 16) & 0xff));
4948
4949 curproxy->check_req[3] = 1;
4950 curproxy->check_req[5] = 130;
4951 curproxy->check_req[11] = 1;
4952 curproxy->check_req[12] = 33;
4953 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4954 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4955 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4956 cur_arg += 3;
4957 } else {
4958 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961 }
4962 } else {
4963 packetlen = userlen + 7;
4964 reqlen = packetlen + 9;
4965
4966 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004967 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004968 curproxy->check_len = reqlen;
4969
4970 snprintf(curproxy->check_req, 4, "%c%c%c",
4971 ((unsigned char) packetlen & 0xff),
4972 ((unsigned char) (packetlen >> 8) & 0xff),
4973 ((unsigned char) (packetlen >> 16) & 0xff));
4974
4975 curproxy->check_req[3] = 1;
4976 curproxy->check_req[5] = 128;
4977 curproxy->check_req[8] = 1;
4978 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4979 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4980 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4981 cur_arg += 2;
4982 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004983 } else {
4984 /* unknown suboption - catchall */
4985 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4986 file, linenum, args[0], args[1]);
4987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
4990 } /* end while loop */
4991 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004992 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004993 else if (!strcmp(args[1], "ldap-check")) {
4994 /* use LDAP request to check servers' health */
4995 free(curproxy->check_req);
4996 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004997 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004998 curproxy->options2 |= PR_O2_LDAP_CHK;
4999
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005000 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005001 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5002 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005003 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5004 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005005 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005006 else if (!strcmp(args[1], "spop-check")) {
5007 if (curproxy == &defproxy) {
5008 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5009 file, linenum, args[0], args[1]);
5010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012 }
5013 if (curproxy->cap & PR_CAP_FE) {
5014 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5015 file, linenum, args[0], args[1]);
5016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
5018 }
5019
5020 /* use SPOE request to check servers' health */
5021 free(curproxy->check_req);
5022 curproxy->check_req = NULL;
5023 curproxy->options2 &= ~PR_O2_CHK_ANY;
5024 curproxy->options2 |= PR_O2_SPOP_CHK;
5025
Christopher Faulet8ef75252017-02-20 22:56:03 +01005026 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005027 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
5031 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5032 goto out;
5033 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005034 else if (!strcmp(args[1], "tcp-check")) {
5035 /* use raw TCPCHK send/expect to check servers' health */
5036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5037 err_code |= ERR_WARN;
5038
5039 free(curproxy->check_req);
5040 curproxy->check_req = NULL;
5041 curproxy->options2 &= ~PR_O2_CHK_ANY;
5042 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005043 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5044 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005045 }
Simon Horman98637e52014-06-20 12:30:16 +09005046 else if (!strcmp(args[1], "external-check")) {
5047 /* excute an external command to check servers' health */
5048 free(curproxy->check_req);
5049 curproxy->check_req = NULL;
5050 curproxy->options2 &= ~PR_O2_CHK_ANY;
5051 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005052 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5053 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005054 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005055 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005056 int cur_arg;
5057
5058 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5059 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005060 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005061
Willy Tarreau87cf5142011-08-19 22:57:24 +02005062 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005063
5064 free(curproxy->fwdfor_hdr_name);
5065 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5066 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5067
5068 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5069 cur_arg = 2;
5070 while (*(args[cur_arg])) {
5071 if (!strcmp(args[cur_arg], "except")) {
5072 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005073 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005074 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5075 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005078 }
5079 /* flush useless bits */
5080 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005081 cur_arg += 2;
5082 } else if (!strcmp(args[cur_arg], "header")) {
5083 /* suboption header - needs additional argument for it */
5084 if (*(args[cur_arg+1]) == 0) {
5085 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5086 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005089 }
5090 free(curproxy->fwdfor_hdr_name);
5091 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5092 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5093 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005094 } else if (!strcmp(args[cur_arg], "if-none")) {
5095 curproxy->options &= ~PR_O_FF_ALWAYS;
5096 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005097 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005098 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005099 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005100 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005103 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005104 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005105 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005106 else if (!strcmp(args[1], "originalto")) {
5107 int cur_arg;
5108
5109 /* insert x-original-to field, but not for the IP address listed as an except.
5110 * set default options (ie: bitfield, header name, etc)
5111 */
5112
5113 curproxy->options |= PR_O_ORGTO;
5114
5115 free(curproxy->orgto_hdr_name);
5116 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5117 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5118
Willy Tarreau87cf5142011-08-19 22:57:24 +02005119 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005120 cur_arg = 2;
5121 while (*(args[cur_arg])) {
5122 if (!strcmp(args[cur_arg], "except")) {
5123 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005124 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 +02005125 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5126 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005129 }
5130 /* flush useless bits */
5131 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5132 cur_arg += 2;
5133 } else if (!strcmp(args[cur_arg], "header")) {
5134 /* suboption header - needs additional argument for it */
5135 if (*(args[cur_arg+1]) == 0) {
5136 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5137 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005140 }
5141 free(curproxy->orgto_hdr_name);
5142 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5143 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5144 cur_arg += 2;
5145 } else {
5146 /* unknown suboption - catchall */
5147 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5148 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005151 }
5152 } /* end while loop */
5153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 else {
5155 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005161 else if (!strcmp(args[0], "default_backend")) {
5162 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005164
5165 if (*(args[1]) == 0) {
5166 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005169 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005170 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005171 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005172
5173 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5174 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005177 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005179
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005180 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5181 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 +01005182 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 /* enable reconnections to dispatch */
5185 curproxy->options |= PR_O_REDISP;
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 Tarreaubaaee002006-06-26 02:48:02 +02005189 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005190 else if (!strcmp(args[0], "http-reuse")) {
5191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5192 err_code |= ERR_WARN;
5193
5194 if (strcmp(args[1], "never") == 0) {
5195 /* enable a graceful server shutdown on an HTTP 404 response */
5196 curproxy->options &= ~PR_O_REUSE_MASK;
5197 curproxy->options |= PR_O_REUSE_NEVR;
5198 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5199 goto out;
5200 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005201 else if (strcmp(args[1], "safe") == 0) {
5202 /* enable a graceful server shutdown on an HTTP 404 response */
5203 curproxy->options &= ~PR_O_REUSE_MASK;
5204 curproxy->options |= PR_O_REUSE_SAFE;
5205 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5206 goto out;
5207 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005208 else if (strcmp(args[1], "aggressive") == 0) {
5209 curproxy->options &= ~PR_O_REUSE_MASK;
5210 curproxy->options |= PR_O_REUSE_AGGR;
5211 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5212 goto out;
5213 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005214 else if (strcmp(args[1], "always") == 0) {
5215 /* enable a graceful server shutdown on an HTTP 404 response */
5216 curproxy->options &= ~PR_O_REUSE_MASK;
5217 curproxy->options |= PR_O_REUSE_ALWS;
5218 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5219 goto out;
5220 }
5221 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005222 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
5225 }
5226 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005227 else if (!strcmp(args[0], "http-check")) {
5228 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005230
5231 if (strcmp(args[1], "disable-on-404") == 0) {
5232 /* enable a graceful server shutdown on an HTTP 404 response */
5233 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005234 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5235 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005236 }
Willy Tarreauef781042010-01-27 11:53:01 +01005237 else if (strcmp(args[1], "send-state") == 0) {
5238 /* enable emission of the apparent state of a server in HTTP checks */
5239 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005240 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5241 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005242 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005243 else if (strcmp(args[1], "expect") == 0) {
5244 const char *ptr_arg;
5245 int cur_arg;
5246
5247 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5248 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
5251 }
5252
5253 cur_arg = 2;
5254 /* consider exclamation marks, sole or at the beginning of a word */
5255 while (*(ptr_arg = args[cur_arg])) {
5256 while (*ptr_arg == '!') {
5257 curproxy->options2 ^= PR_O2_EXP_INV;
5258 ptr_arg++;
5259 }
5260 if (*ptr_arg)
5261 break;
5262 cur_arg++;
5263 }
5264 /* now ptr_arg points to the beginning of a word past any possible
5265 * exclamation mark, and cur_arg is the argument which holds this word.
5266 */
5267 if (strcmp(ptr_arg, "status") == 0) {
5268 if (!*(args[cur_arg + 1])) {
5269 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5270 file, linenum, args[0], args[1], ptr_arg);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005275 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005276 curproxy->expect_str = strdup(args[cur_arg + 1]);
5277 }
5278 else if (strcmp(ptr_arg, "string") == 0) {
5279 if (!*(args[cur_arg + 1])) {
5280 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5281 file, linenum, args[0], args[1], ptr_arg);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005286 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005287 curproxy->expect_str = strdup(args[cur_arg + 1]);
5288 }
5289 else if (strcmp(ptr_arg, "rstatus") == 0) {
5290 if (!*(args[cur_arg + 1])) {
5291 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5292 file, linenum, args[0], args[1], ptr_arg);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005297 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005298 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005299 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005300 free(curproxy->expect_regex);
5301 curproxy->expect_regex = NULL;
5302 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005303 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005304 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5305 error = NULL;
5306 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5307 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5308 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5309 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 }
5314 else if (strcmp(ptr_arg, "rstring") == 0) {
5315 if (!*(args[cur_arg + 1])) {
5316 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5317 file, linenum, args[0], args[1], ptr_arg);
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005322 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005323 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005324 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005325 free(curproxy->expect_regex);
5326 curproxy->expect_regex = NULL;
5327 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005328 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005329 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5330 error = NULL;
5331 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5332 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5333 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5334 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338 }
5339 else {
5340 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5341 file, linenum, args[0], args[1], ptr_arg);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005346 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005347 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 +02005348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005350 }
5351 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005352 else if (!strcmp(args[0], "tcp-check")) {
5353 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5354 err_code |= ERR_WARN;
5355
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005356 if (strcmp(args[1], "comment") == 0) {
5357 int cur_arg;
5358 struct tcpcheck_rule *tcpcheck;
5359
5360 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005361 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005362 tcpcheck->action = TCPCHK_ACT_COMMENT;
5363
5364 if (!*args[cur_arg + 1]) {
5365 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5366 file, linenum, args[cur_arg]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370
5371 tcpcheck->comment = strdup(args[cur_arg + 1]);
5372
5373 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005374 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5375 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005376 }
5377 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005378 const char *ptr_arg;
5379 int cur_arg;
5380 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005381
5382 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005383 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5384 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5385 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5386 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5387 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005388
Willy Tarreau5581c272015-05-13 12:24:53 +02005389 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5390 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5391 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5392 file, linenum);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005395 }
5396
5397 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005398 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005399 tcpcheck->action = TCPCHK_ACT_CONNECT;
5400
5401 /* parsing each parameters to fill up the rule */
5402 while (*(ptr_arg = args[cur_arg])) {
5403 /* tcp port */
5404 if (strcmp(args[cur_arg], "port") == 0) {
5405 if ( (atol(args[cur_arg + 1]) > 65535) ||
5406 (atol(args[cur_arg + 1]) < 1) ){
5407 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5408 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412 tcpcheck->port = atol(args[cur_arg + 1]);
5413 cur_arg += 2;
5414 }
5415 /* send proxy protocol */
5416 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5417 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5418 cur_arg++;
5419 }
5420#ifdef USE_OPENSSL
5421 else if (strcmp(args[cur_arg], "ssl") == 0) {
5422 curproxy->options |= PR_O_TCPCHK_SSL;
5423 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5424 cur_arg++;
5425 }
5426#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005427 /* comment for this tcpcheck line */
5428 else if (strcmp(args[cur_arg], "comment") == 0) {
5429 if (!*args[cur_arg + 1]) {
5430 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5431 file, linenum, args[cur_arg]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435 tcpcheck->comment = strdup(args[cur_arg + 1]);
5436 cur_arg += 2;
5437 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005438 else {
5439#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005440 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 +01005441#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005442 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 +01005443#endif /* USE_OPENSSL */
5444 file, linenum, args[0], args[1], args[cur_arg]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
5448
5449 }
5450
5451 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5452 }
5453 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454 if (! *(args[2]) ) {
5455 /* SEND string expected */
5456 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5457 file, linenum, args[0], args[1], args[2]);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 } else {
5461 struct tcpcheck_rule *tcpcheck;
5462
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005463 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005464
5465 tcpcheck->action = TCPCHK_ACT_SEND;
5466 tcpcheck->string_len = strlen(args[2]);
5467 tcpcheck->string = strdup(args[2]);
5468 tcpcheck->expect_regex = NULL;
5469
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005470 /* comment for this tcpcheck line */
5471 if (strcmp(args[3], "comment") == 0) {
5472 if (!*args[4]) {
5473 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5474 file, linenum, args[3]);
5475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
5477 }
5478 tcpcheck->comment = strdup(args[4]);
5479 }
5480
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005481 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5482 }
5483 }
5484 else if (strcmp(args[1], "send-binary") == 0) {
5485 if (! *(args[2]) ) {
5486 /* SEND binary string expected */
5487 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5488 file, linenum, args[0], args[1], args[2]);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 } else {
5492 struct tcpcheck_rule *tcpcheck;
5493 char *err = NULL;
5494
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005495 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005496
5497 tcpcheck->action = TCPCHK_ACT_SEND;
5498 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5499 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5500 file, linenum, args[0], args[1], args[2], err);
5501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
5503 }
5504 tcpcheck->expect_regex = NULL;
5505
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005506 /* comment for this tcpcheck line */
5507 if (strcmp(args[3], "comment") == 0) {
5508 if (!*args[4]) {
5509 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5510 file, linenum, args[3]);
5511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
5513 }
5514 tcpcheck->comment = strdup(args[4]);
5515 }
5516
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005517 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5518 }
5519 }
5520 else if (strcmp(args[1], "expect") == 0) {
5521 const char *ptr_arg;
5522 int cur_arg;
5523 int inverse = 0;
5524
5525 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5526 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530
5531 cur_arg = 2;
5532 /* consider exclamation marks, sole or at the beginning of a word */
5533 while (*(ptr_arg = args[cur_arg])) {
5534 while (*ptr_arg == '!') {
5535 inverse = !inverse;
5536 ptr_arg++;
5537 }
5538 if (*ptr_arg)
5539 break;
5540 cur_arg++;
5541 }
5542 /* now ptr_arg points to the beginning of a word past any possible
5543 * exclamation mark, and cur_arg is the argument which holds this word.
5544 */
5545 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005546 struct tcpcheck_rule *tcpcheck;
5547 char *err = NULL;
5548
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005549 if (!*(args[cur_arg + 1])) {
5550 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5551 file, linenum, args[0], args[1], ptr_arg);
5552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
5554 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005556 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005557
5558 tcpcheck->action = TCPCHK_ACT_EXPECT;
5559 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5560 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5561 file, linenum, args[0], args[1], args[2], err);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565 tcpcheck->expect_regex = NULL;
5566 tcpcheck->inverse = inverse;
5567
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005568 /* tcpcheck comment */
5569 cur_arg += 2;
5570 if (strcmp(args[cur_arg], "comment") == 0) {
5571 if (!*args[cur_arg + 1]) {
5572 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5573 file, linenum, args[cur_arg + 1]);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
5577 tcpcheck->comment = strdup(args[cur_arg + 1]);
5578 }
5579
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5581 }
5582 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005583 struct tcpcheck_rule *tcpcheck;
5584
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005585 if (!*(args[cur_arg + 1])) {
5586 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5587 file, linenum, args[0], args[1], ptr_arg);
5588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
5590 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005591
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005592 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005593
5594 tcpcheck->action = TCPCHK_ACT_EXPECT;
5595 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5596 tcpcheck->string = strdup(args[cur_arg + 1]);
5597 tcpcheck->expect_regex = NULL;
5598 tcpcheck->inverse = inverse;
5599
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005600 /* tcpcheck comment */
5601 cur_arg += 2;
5602 if (strcmp(args[cur_arg], "comment") == 0) {
5603 if (!*args[cur_arg + 1]) {
5604 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5605 file, linenum, args[cur_arg + 1]);
5606 err_code |= ERR_ALERT | ERR_FATAL;
5607 goto out;
5608 }
5609 tcpcheck->comment = strdup(args[cur_arg + 1]);
5610 }
5611
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5613 }
5614 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005615 struct tcpcheck_rule *tcpcheck;
5616
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005617 if (!*(args[cur_arg + 1])) {
5618 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5619 file, linenum, args[0], args[1], ptr_arg);
5620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
5622 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005623
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005624 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005625
5626 tcpcheck->action = TCPCHK_ACT_EXPECT;
5627 tcpcheck->string_len = 0;
5628 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005629 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5630 error = NULL;
5631 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5632 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5633 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5634 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
5638 tcpcheck->inverse = inverse;
5639
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005640 /* tcpcheck comment */
5641 cur_arg += 2;
5642 if (strcmp(args[cur_arg], "comment") == 0) {
5643 if (!*args[cur_arg + 1]) {
5644 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5645 file, linenum, args[cur_arg + 1]);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649 tcpcheck->comment = strdup(args[cur_arg + 1]);
5650 }
5651
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005652 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5653 }
5654 else {
5655 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5656 file, linenum, args[0], args[1], ptr_arg);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660 }
5661 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005662 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
5665 }
5666 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005667 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005668 if (curproxy == &defproxy) {
5669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005672 }
5673
Willy Tarreaub80c2302007-11-30 20:51:32 +01005674 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005675 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005676
5677 if (strcmp(args[1], "fail") == 0) {
5678 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005679 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005680 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5681 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005684 }
5685
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005686 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5687 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5688 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005691 }
5692 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5693 }
5694 else {
5695 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02005700#ifdef TPROXY
5701 else if (!strcmp(args[0], "transparent")) {
5702 /* enable transparent proxy connections */
5703 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005704 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 }
5707#endif
5708 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005711
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 if (*(args[1]) == 0) {
5713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 }
5717 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005721 else if (!strcmp(args[0], "backlog")) { /* backlog */
5722 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005723 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005724
5725 if (*(args[1]) == 0) {
5726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005729 }
5730 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005731 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5732 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005733 }
Willy Tarreau86034312006-12-29 00:10:33 +01005734 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005737
Willy Tarreau86034312006-12-29 00:10:33 +01005738 if (*(args[1]) == 0) {
5739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005742 }
5743 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005744 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5745 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5748 if (*(args[1]) == 0) {
5749 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005753 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5754 if (err) {
5755 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5756 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005757 err_code |= ERR_ALERT | ERR_FATAL;
5758 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005759 }
5760 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 }
5764 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005765 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005766 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005767 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005768
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 if (curproxy == &defproxy) {
5770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005774 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005776
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005777 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005778 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005779 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005780 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005781 goto out;
5782 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005783
5784 proto = protocol_by_family(sk->ss_family);
5785 if (!proto || !proto->connect) {
5786 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5787 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
5790 }
5791
5792 if (port1 != port2) {
5793 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5794 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005798
5799 if (!port1) {
5800 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5801 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005805
William Lallemanddf1425a2015-04-28 20:17:49 +02005806 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5807 goto out;
5808
Willy Tarreaud5191e72010-02-09 20:50:45 +01005809 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005810 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 }
5812 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005813 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005815
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005816 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5817 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_ALERT | ERR_FATAL;
5819 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005822 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005823 /**
5824 * The syntax for hash-type config element is
5825 * hash-type {map-based|consistent} [[<algo>] avalanche]
5826 *
5827 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5828 */
5829 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005830
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005831 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5832 err_code |= ERR_WARN;
5833
5834 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005835 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5836 }
5837 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005838 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5839 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005840 else if (strcmp(args[1], "avalanche") == 0) {
5841 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]);
5842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005844 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005845 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005846 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005847 err_code |= ERR_ALERT | ERR_FATAL;
5848 goto out;
5849 }
Bhaskar98634f02013-10-29 23:30:51 -04005850
5851 /* set the hash function to use */
5852 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005853 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005854 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005855
5856 /* if consistent with no argument, then avalanche modifier is also applied */
5857 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5858 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005859 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005860 /* set the hash function */
5861 if (!strcmp(args[2], "sdbm")) {
5862 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5863 }
5864 else if (!strcmp(args[2], "djb2")) {
5865 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005866 }
5867 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005868 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005869 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005870 else if (!strcmp(args[2], "crc32")) {
5871 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5872 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005873 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005874 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 -05005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
5878
5879 /* set the hash modifier */
5880 if (!strcmp(args[3], "avalanche")) {
5881 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5882 }
5883 else if (*args[3]) {
5884 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005888 }
William Lallemanda73203e2012-03-12 12:48:57 +01005889 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005890 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5891 if (*(args[1]) == 0) {
5892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
5896 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5897 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5898 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902 }
William Lallemanda73203e2012-03-12 12:48:57 +01005903 else if (strcmp(args[0], "unique-id-format") == 0) {
5904 if (!*(args[1])) {
5905 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5906 err_code |= ERR_ALERT | ERR_FATAL;
5907 goto out;
5908 }
William Lallemand3203ff42012-11-11 17:30:56 +01005909 if (*(args[2])) {
5910 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5911 err_code |= ERR_ALERT | ERR_FATAL;
5912 goto out;
5913 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005914 free(curproxy->conf.uniqueid_format_string);
5915 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005916
Willy Tarreau62a61232013-04-12 18:13:46 +02005917 free(curproxy->conf.uif_file);
5918 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5919 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005920 }
William Lallemanda73203e2012-03-12 12:48:57 +01005921
5922 else if (strcmp(args[0], "unique-id-header") == 0) {
5923 if (!*(args[1])) {
5924 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5925 err_code |= ERR_ALERT | ERR_FATAL;
5926 goto out;
5927 }
5928 free(curproxy->header_unique_id);
5929 curproxy->header_unique_id = strdup(args[1]);
5930 }
5931
William Lallemand723b73a2012-02-08 16:37:49 +01005932 else if (strcmp(args[0], "log-format") == 0) {
5933 if (!*(args[1])) {
5934 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
William Lallemand3203ff42012-11-11 17:30:56 +01005938 if (*(args[2])) {
5939 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005943 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5944 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005945
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005946 if (curproxy->conf.logformat_string == default_http_log_format)
5947 oldlogformat = "option httplog";
5948 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5949 oldlogformat = "option tcplog";
5950 else if (curproxy->conf.logformat_string == clf_http_log_format)
5951 oldlogformat = "option httplog clf";
5952 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5953 file, linenum, oldlogformat);
5954 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005955 if (curproxy->conf.logformat_string != default_http_log_format &&
5956 curproxy->conf.logformat_string != default_tcp_log_format &&
5957 curproxy->conf.logformat_string != clf_http_log_format)
5958 free(curproxy->conf.logformat_string);
5959 curproxy->conf.logformat_string = strdup(args[1]);
5960
5961 free(curproxy->conf.lfs_file);
5962 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5963 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005964
5965 /* get a chance to improve log-format error reporting by
5966 * reporting the correct line-number when possible.
5967 */
5968 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5969 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5970 file, linenum, curproxy->id);
5971 err_code |= ERR_WARN;
5972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005974 else if (!strcmp(args[0], "log-format-sd")) {
5975 if (!*(args[1])) {
5976 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
5979 }
5980 if (*(args[2])) {
5981 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5982 err_code |= ERR_ALERT | ERR_FATAL;
5983 goto out;
5984 }
5985
5986 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5987 free(curproxy->conf.logformat_sd_string);
5988 curproxy->conf.logformat_sd_string = strdup(args[1]);
5989
5990 free(curproxy->conf.lfsd_file);
5991 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5992 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5993
5994 /* get a chance to improve log-format-sd error reporting by
5995 * reporting the correct line-number when possible.
5996 */
5997 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5998 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5999 file, linenum, curproxy->id);
6000 err_code |= ERR_WARN;
6001 }
6002 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006003 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6004 if (*(args[1]) == 0) {
6005 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006009 chunk_destroy(&curproxy->log_tag);
6010 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006011 }
William Lallemand0f99e342011-10-12 17:50:54 +02006012 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6013 /* delete previous herited or defined syslog servers */
6014 struct logsrv *back;
6015
6016 if (*(args[1]) != 0) {
6017 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021
William Lallemand723b73a2012-02-08 16:37:49 +01006022 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6023 LIST_DEL(&tmplogsrv->list);
6024 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006025 }
6026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006028 struct logsrv *logsrv;
6029
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006031 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006032 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006033 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006034 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006035 LIST_INIT(&node->list);
6036 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 }
6039 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006040 struct sockaddr_storage *sk;
6041 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006042 int arg = 0;
6043 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006044
Vincent Bernat02779b62016-04-03 13:48:43 +02006045 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006046
Willy Tarreau18324f52014-06-27 18:10:07 +02006047 /* just after the address, a length may be specified */
6048 if (strcmp(args[arg+2], "len") == 0) {
6049 len = atoi(args[arg+3]);
6050 if (len < 80 || len > 65535) {
6051 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6052 file, linenum, args[arg+3]);
6053 err_code |= ERR_ALERT | ERR_FATAL;
6054 goto out;
6055 }
6056 logsrv->maxlen = len;
6057
6058 /* skip these two args */
6059 arg += 2;
6060 }
6061 else
6062 logsrv->maxlen = MAX_SYSLOG_LEN;
6063
6064 if (logsrv->maxlen > global.max_syslog_len) {
6065 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006066 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6067 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6068 logline = my_realloc2(logline, global.max_syslog_len + 1);
6069 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006070 }
6071
Dragan Dosen1322d092015-09-22 16:05:32 +02006072 /* after the length, a format may be specified */
6073 if (strcmp(args[arg+2], "format") == 0) {
6074 logsrv->format = get_log_format(args[arg+3]);
6075 if (logsrv->format < 0) {
6076 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6077 err_code |= ERR_ALERT | ERR_FATAL;
6078 goto out;
6079 }
6080
6081 /* skip these two args */
6082 arg += 2;
6083 }
6084
William Lallemanddf1425a2015-04-28 20:17:49 +02006085 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6086 goto out;
6087
Willy Tarreau18324f52014-06-27 18:10:07 +02006088 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006089 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006090 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006091 err_code |= ERR_ALERT | ERR_FATAL;
6092 goto out;
6093
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094 }
6095
William Lallemand0f99e342011-10-12 17:50:54 +02006096 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006097 if (*(args[arg+3])) {
6098 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006099 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006100 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006101 err_code |= ERR_ALERT | ERR_FATAL;
6102 goto out;
6103
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 }
6105 }
6106
William Lallemand0f99e342011-10-12 17:50:54 +02006107 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006108 if (*(args[arg+4])) {
6109 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006110 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006111 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
6114
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006115 }
6116 }
6117
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006118 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006119 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006120 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006121 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006122 goto out;
6123 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006124
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006125 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006126
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006127 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006128 if (port1 != port2) {
6129 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6130 file, linenum, args[0], args[1]);
6131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133 }
6134
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006136 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 }
William Lallemand0f99e342011-10-12 17:50:54 +02006138
6139 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 }
6141 else {
6142 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6143 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006144 err_code |= ERR_ALERT | ERR_FATAL;
6145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146 }
6147 }
6148 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006149 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006150 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006151 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006152 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006153
Willy Tarreau977b8e42006-12-29 14:19:17 +01006154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006156
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6159 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006163
6164 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006165 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6166 free(curproxy->conn_src.iface_name);
6167 curproxy->conn_src.iface_name = NULL;
6168 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006169
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006170 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006171 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006172 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006173 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006174 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006175 goto out;
6176 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006177
6178 proto = protocol_by_family(sk->ss_family);
6179 if (!proto || !proto->connect) {
6180 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006181 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
6184 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006185
6186 if (port1 != port2) {
6187 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6188 file, linenum, args[0], args[1]);
6189 err_code |= ERR_ALERT | ERR_FATAL;
6190 goto out;
6191 }
6192
Willy Tarreauef9a3602012-12-08 22:29:20 +01006193 curproxy->conn_src.source_addr = *sk;
6194 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006195
6196 cur_arg = 2;
6197 while (*(args[cur_arg])) {
6198 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006199#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006200 if (!*args[cur_arg + 1]) {
6201 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6202 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006205 }
6206
6207 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006208 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6209 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006210 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006211 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6212 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006213 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6214 char *name, *end;
6215
6216 name = args[cur_arg+1] + 7;
6217 while (isspace(*name))
6218 name++;
6219
6220 end = name;
6221 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6222 end++;
6223
Willy Tarreauef9a3602012-12-08 22:29:20 +01006224 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6225 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6226 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6227 curproxy->conn_src.bind_hdr_len = end - name;
6228 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6229 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6230 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006231
6232 /* now look for an occurrence number */
6233 while (isspace(*end))
6234 end++;
6235 if (*end == ',') {
6236 end++;
6237 name = end;
6238 if (*end == '-')
6239 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006240 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006241 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006242 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006243 }
6244
Willy Tarreauef9a3602012-12-08 22:29:20 +01006245 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006246 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6247 " occurrences values smaller than %d.\n",
6248 file, linenum, MAX_HDR_HISTORY);
6249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
6251 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006252 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006253 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006254
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006255 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006256 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006257 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006258 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006259 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006260 goto out;
6261 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006262
6263 proto = protocol_by_family(sk->ss_family);
6264 if (!proto || !proto->connect) {
6265 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6266 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006267 err_code |= ERR_ALERT | ERR_FATAL;
6268 goto out;
6269 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006270
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006271 if (port1 != port2) {
6272 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6273 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006274 err_code |= ERR_ALERT | ERR_FATAL;
6275 goto out;
6276 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006277 curproxy->conn_src.tproxy_addr = *sk;
6278 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006279 }
6280 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006281#else /* no TPROXY support */
6282 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006283 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006284 err_code |= ERR_ALERT | ERR_FATAL;
6285 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006286#endif
6287 cur_arg += 2;
6288 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006289 }
6290
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006291 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6292#ifdef SO_BINDTODEVICE
6293 if (!*args[cur_arg + 1]) {
6294 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6295 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006296 err_code |= ERR_ALERT | ERR_FATAL;
6297 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006298 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006299 free(curproxy->conn_src.iface_name);
6300 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6301 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302 global.last_checks |= LSTCHK_NETADM;
6303#else
6304 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6305 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006308#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006309 cur_arg += 2;
6310 continue;
6311 }
6312 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006313 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006318 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6319 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6320 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331
6332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006334 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006366 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6376 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006377 err_code |= ERR_ALERT | ERR_FATAL;
6378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380
6381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006382 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006383 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 }
6387 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006389 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006390 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 }
6394 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006396 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006397 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006398 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 }
6401 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006403 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006404 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 }
6408 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006410 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006415 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006417 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006418 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006419 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006420 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006423 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006424
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 if (curproxy == &defproxy) {
6426 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006427 err_code |= ERR_ALERT | ERR_FATAL;
6428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006430 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006431 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 if (*(args[1]) == 0) {
6434 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006435 err_code |= ERR_ALERT | ERR_FATAL;
6436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006438
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006439 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006440 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6441 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6442 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006443 err_code |= ERR_ALERT | ERR_FATAL;
6444 goto out;
6445 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006446 err_code |= warnif_cond_conflicts(cond,
6447 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6448 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006449 }
6450 else if (*args[2]) {
6451 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6452 file, linenum, args[0], args[2]);
6453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
6455 }
6456
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006457 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006458 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006459 wl->s = strdup(args[1]);
6460 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006461 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006465 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006467 err_code |= ERR_ALERT | ERR_FATAL;
6468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006470
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006473 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
6477 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006479 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006486 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006487 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006488 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
6491 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006493 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6494 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006495 err_code |= ERR_ALERT | ERR_FATAL;
6496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 }
6498
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006500 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006501 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
6505 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006507 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006514 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006515 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006516 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 }
6519 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006520 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006521
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 if (curproxy == &defproxy) {
6523 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006524 err_code |= ERR_ALERT | ERR_FATAL;
6525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006527 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006528 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 if (*(args[1]) == 0) {
6531 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006532 err_code |= ERR_ALERT | ERR_FATAL;
6533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
6535
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006536 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006537 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6538 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6539 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006540 err_code |= ERR_ALERT | ERR_FATAL;
6541 goto out;
6542 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006543 err_code |= warnif_cond_conflicts(cond,
6544 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6545 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006546 }
6547 else if (*args[2]) {
6548 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6549 file, linenum, args[0], args[2]);
6550 err_code |= ERR_ALERT | ERR_FATAL;
6551 goto out;
6552 }
6553
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006554 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006556 wl->s = strdup(args[1]);
6557 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558 }
6559 else if (!strcmp(args[0], "errorloc") ||
6560 !strcmp(args[0], "errorloc302") ||
6561 !strcmp(args[0], "errorloc303")) { /* error location */
6562 int errnum, errlen;
6563 char *err;
6564
Willy Tarreau977b8e42006-12-29 14:19:17 +01006565 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006566 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006567
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006569 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
6571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 }
6573
6574 errnum = atol(args[1]);
6575 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006576 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6577 err = malloc(errlen);
6578 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006580 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6581 err = malloc(errlen);
6582 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 }
6584
Willy Tarreau0f772532006-12-23 20:51:41 +01006585 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6586 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006587 chunk_destroy(&curproxy->errmsg[rc]);
6588 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006589 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006592
6593 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006594 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6595 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 free(err);
6597 }
6598 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006599 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6600 int errnum, errlen, fd;
6601 char *err;
6602 struct stat stat;
6603
6604 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006605 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006606
6607 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006608 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006609 err_code |= ERR_ALERT | ERR_FATAL;
6610 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006611 }
6612
6613 fd = open(args[2], O_RDONLY);
6614 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6615 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6616 file, linenum, args[2], args[1]);
6617 if (fd >= 0)
6618 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006619 err_code |= ERR_ALERT | ERR_FATAL;
6620 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006621 }
6622
Willy Tarreau27a674e2009-08-17 07:23:33 +02006623 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006624 errlen = stat.st_size;
6625 } else {
6626 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006627 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006629 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006630 }
6631
6632 err = malloc(errlen); /* malloc() must succeed during parsing */
6633 errnum = read(fd, err, errlen);
6634 if (errnum != errlen) {
6635 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6636 file, linenum, args[2], args[1]);
6637 close(fd);
6638 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006639 err_code |= ERR_ALERT | ERR_FATAL;
6640 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006641 }
6642 close(fd);
6643
6644 errnum = atol(args[1]);
6645 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6646 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006647 chunk_destroy(&curproxy->errmsg[rc]);
6648 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006649 break;
6650 }
6651 }
6652
6653 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006654 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6655 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006656 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006657 free(err);
6658 }
6659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006660 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006661 struct cfg_kw_list *kwl;
6662 int index;
6663
6664 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6665 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6666 if (kwl->kw[index].section != CFG_LISTEN)
6667 continue;
6668 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6669 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006670 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006671 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006672 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006673 err_code |= ERR_ALERT | ERR_FATAL;
6674 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006675 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006676 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006677 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006678 err_code |= ERR_WARN;
6679 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006680 }
Willy Tarreau93893792009-07-23 13:19:11 +02006681 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006682 }
6683 }
6684 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006685
Willy Tarreau6daf3432008-01-22 16:44:08 +01006686 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006687 err_code |= ERR_ALERT | ERR_FATAL;
6688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006689 }
Willy Tarreau93893792009-07-23 13:19:11 +02006690 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006691 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006692 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006693}
6694
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006695int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006696cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6697{
6698#ifdef CONFIG_HAP_NS
6699 const char *err;
6700 const char *item = args[0];
6701
6702 if (!strcmp(item, "namespace_list")) {
6703 return 0;
6704 }
6705 else if (!strcmp(item, "namespace")) {
6706 size_t idx = 1;
6707 const char *current;
6708 while (*(current = args[idx++])) {
6709 err = invalid_char(current);
6710 if (err) {
6711 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6712 file, linenum, *err, item, current);
6713 return ERR_ALERT | ERR_FATAL;
6714 }
6715
6716 if (netns_store_lookup(current, strlen(current))) {
6717 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6718 file, linenum, current);
6719 return ERR_ALERT | ERR_FATAL;
6720 }
6721 if (!netns_store_insert(current)) {
6722 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6723 file, linenum, current);
6724 return ERR_ALERT | ERR_FATAL;
6725 }
6726 }
6727 }
6728
6729 return 0;
6730#else
6731 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6732 file, linenum);
6733 return ERR_ALERT | ERR_FATAL;
6734#endif
6735}
6736
6737int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006738cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6739{
6740
6741 int err_code = 0;
6742 const char *err;
6743
6744 if (!strcmp(args[0], "userlist")) { /* new userlist */
6745 struct userlist *newul;
6746
6747 if (!*args[1]) {
6748 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6749 file, linenum, args[0]);
6750 err_code |= ERR_ALERT | ERR_FATAL;
6751 goto out;
6752 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6754 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006755
6756 err = invalid_char(args[1]);
6757 if (err) {
6758 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6759 file, linenum, *err, args[0], args[1]);
6760 err_code |= ERR_ALERT | ERR_FATAL;
6761 goto out;
6762 }
6763
6764 for (newul = userlist; newul; newul = newul->next)
6765 if (!strcmp(newul->name, args[1])) {
6766 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6767 file, linenum, args[1]);
6768 err_code |= ERR_WARN;
6769 goto out;
6770 }
6771
Vincent Bernat02779b62016-04-03 13:48:43 +02006772 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006773 if (!newul) {
6774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6775 err_code |= ERR_ALERT | ERR_ABORT;
6776 goto out;
6777 }
6778
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006779 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006780 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006781 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6782 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006783 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006784 goto out;
6785 }
6786
6787 newul->next = userlist;
6788 userlist = newul;
6789
6790 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006791 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006793 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794
6795 if (!*args[1]) {
6796 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6797 file, linenum, args[0]);
6798 err_code |= ERR_ALERT | ERR_FATAL;
6799 goto out;
6800 }
6801
6802 err = invalid_char(args[1]);
6803 if (err) {
6804 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6805 file, linenum, *err, args[0], args[1]);
6806 err_code |= ERR_ALERT | ERR_FATAL;
6807 goto out;
6808 }
6809
William Lallemand4ac9f542015-05-28 18:03:51 +02006810 if (!userlist)
6811 goto out;
6812
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006813 for (ag = userlist->groups; ag; ag = ag->next)
6814 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6816 file, linenum, args[1], userlist->name);
6817 err_code |= ERR_ALERT;
6818 goto out;
6819 }
6820
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006821 ag = calloc(1, sizeof(*ag));
6822 if (!ag) {
6823 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6824 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006825 goto out;
6826 }
6827
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006828 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006829 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006830 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6831 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006832 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006833 goto out;
6834 }
6835
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006836 cur_arg = 2;
6837
6838 while (*args[cur_arg]) {
6839 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006840 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006841 cur_arg += 2;
6842 continue;
6843 } else {
6844 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6845 file, linenum, args[0]);
6846 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006847 free(ag->groupusers);
6848 free(ag->name);
6849 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006850 goto out;
6851 }
6852 }
6853
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006854 ag->next = userlist->groups;
6855 userlist->groups = ag;
6856
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 } else if (!strcmp(args[0], "user")) { /* new user */
6858 struct auth_users *newuser;
6859 int cur_arg;
6860
6861 if (!*args[1]) {
6862 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6863 file, linenum, args[0]);
6864 err_code |= ERR_ALERT | ERR_FATAL;
6865 goto out;
6866 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006867 if (!userlist)
6868 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869
6870 for (newuser = userlist->users; newuser; newuser = newuser->next)
6871 if (!strcmp(newuser->user, args[1])) {
6872 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6873 file, linenum, args[1], userlist->name);
6874 err_code |= ERR_ALERT;
6875 goto out;
6876 }
6877
Vincent Bernat02779b62016-04-03 13:48:43 +02006878 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006879 if (!newuser) {
6880 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6881 err_code |= ERR_ALERT | ERR_ABORT;
6882 goto out;
6883 }
6884
6885 newuser->user = strdup(args[1]);
6886
6887 newuser->next = userlist->users;
6888 userlist->users = newuser;
6889
6890 cur_arg = 2;
6891
6892 while (*args[cur_arg]) {
6893 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006894#ifdef CONFIG_HAP_CRYPT
6895 if (!crypt("", args[cur_arg + 1])) {
6896 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6897 file, linenum, newuser->user);
6898 err_code |= ERR_ALERT | ERR_FATAL;
6899 goto out;
6900 }
6901#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006902 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6903 file, linenum);
6904 err_code |= ERR_ALERT;
6905#endif
6906 newuser->pass = strdup(args[cur_arg + 1]);
6907 cur_arg += 2;
6908 continue;
6909 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6910 newuser->pass = strdup(args[cur_arg + 1]);
6911 newuser->flags |= AU_O_INSECURE;
6912 cur_arg += 2;
6913 continue;
6914 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006915 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006916 cur_arg += 2;
6917 continue;
6918 } else {
6919 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6920 file, linenum, args[0]);
6921 err_code |= ERR_ALERT | ERR_FATAL;
6922 goto out;
6923 }
6924 }
6925 } else {
6926 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6927 err_code |= ERR_ALERT | ERR_FATAL;
6928 }
6929
6930out:
6931 return err_code;
6932}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933
Christopher Faulet79bdef32016-11-04 22:36:15 +01006934int
6935cfg_parse_scope(const char *file, int linenum, char *line)
6936{
6937 char *beg, *end, *scope = NULL;
6938 int err_code = 0;
6939 const char *err;
6940
6941 beg = line + 1;
6942 end = strchr(beg, ']');
6943
6944 /* Detect end of scope declaration */
6945 if (!end || end == beg) {
6946 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6947 file, linenum);
6948 err_code |= ERR_ALERT | ERR_FATAL;
6949 goto out;
6950 }
6951
6952 /* Get scope name and check its validity */
6953 scope = my_strndup(beg, end-beg);
6954 err = invalid_char(scope);
6955 if (err) {
6956 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6957 file, linenum, *err);
6958 err_code |= ERR_ALERT | ERR_ABORT;
6959 goto out;
6960 }
6961
6962 /* Be sure to have a scope declaration alone on its line */
6963 line = end+1;
6964 while (isspace((unsigned char)*line))
6965 line++;
6966 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6967 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6968 file, linenum, *line);
6969 err_code |= ERR_ALERT | ERR_ABORT;
6970 goto out;
6971 }
6972
6973 /* We have a valid scope declaration, save it */
6974 free(cfg_scope);
6975 cfg_scope = scope;
6976 scope = NULL;
6977
6978 out:
6979 free(scope);
6980 return err_code;
6981}
6982
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983/*
6984 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006985 * Returns the error code, 0 if OK, or any combination of :
6986 * - ERR_ABORT: must abort ASAP
6987 * - ERR_FATAL: we can continue parsing but not start the service
6988 * - ERR_WARN: a warning has been emitted
6989 * - ERR_ALERT: an alert has been emitted
6990 * Only the two first ones can stop processing, the two others are just
6991 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006992 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006993int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006994{
William Lallemand64e84512015-05-12 14:25:37 +02006995 char *thisline;
6996 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006997 FILE *f;
6998 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006999 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007000 struct cfg_section *cs = NULL;
7001 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007002 int readbytes = 0;
7003
7004 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007005 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007006 return -1;
7007 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007008
David Carlier97880bb2016-04-08 10:35:26 +01007009 if ((f=fopen(file,"r")) == NULL) {
7010 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013
William Lallemandb2f07452015-05-12 14:27:13 +02007014next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007015 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007016 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007017 char *end;
7018 char *args[MAX_LINE_ARGS + 1];
7019 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007020 int dquote = 0; /* double quote */
7021 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007022
Willy Tarreaubaaee002006-06-26 02:48:02 +02007023 linenum++;
7024
7025 end = line + strlen(line);
7026
William Lallemand64e84512015-05-12 14:25:37 +02007027 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007028 /* Check if we reached the limit and the last char is not \n.
7029 * Watch out for the last line without the terminating '\n'!
7030 */
William Lallemand64e84512015-05-12 14:25:37 +02007031 char *newline;
7032 int newlinesize = linesize * 2;
7033
7034 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7035 if (newline == NULL) {
7036 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7037 file, linenum);
7038 err_code |= ERR_ALERT | ERR_FATAL;
7039 continue;
7040 }
7041
7042 readbytes = linesize - 1;
7043 linesize = newlinesize;
7044 thisline = newline;
7045 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007046 }
7047
William Lallemand64e84512015-05-12 14:25:37 +02007048 readbytes = 0;
7049
Willy Tarreaubaaee002006-06-26 02:48:02 +02007050 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007051 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007052 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007053
Christopher Faulet79bdef32016-11-04 22:36:15 +01007054
7055 if (*line == '[') {/* This is the begining if a scope */
7056 err_code |= cfg_parse_scope(file, linenum, line);
7057 goto next_line;
7058 }
7059
Willy Tarreaubaaee002006-06-26 02:48:02 +02007060 arg = 0;
7061 args[arg] = line;
7062
7063 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007064 if (*line == '"' && !squote) { /* double quote outside single quotes */
7065 if (dquote)
7066 dquote = 0;
7067 else
7068 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007069 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007070 end--;
7071 }
7072 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7073 if (squote)
7074 squote = 0;
7075 else
7076 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007077 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007078 end--;
7079 }
7080 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007081 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7082 * C equivalent value. Other combinations left unchanged (eg: \1).
7083 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007084 int skip = 0;
7085 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7086 *line = line[1];
7087 skip = 1;
7088 }
7089 else if (line[1] == 'r') {
7090 *line = '\r';
7091 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 else if (line[1] == 'n') {
7094 *line = '\n';
7095 skip = 1;
7096 }
7097 else if (line[1] == 't') {
7098 *line = '\t';
7099 skip = 1;
7100 }
7101 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007102 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103 unsigned char hex1, hex2;
7104 hex1 = toupper(line[2]) - '0';
7105 hex2 = toupper(line[3]) - '0';
7106 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7107 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7108 *line = (hex1<<4) + hex2;
7109 skip = 3;
7110 }
7111 else {
7112 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007115 } else if (line[1] == '"') {
7116 *line = '"';
7117 skip = 1;
7118 } else if (line[1] == '\'') {
7119 *line = '\'';
7120 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007121 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7122 *line = '$';
7123 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 }
7125 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007126 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007127 end -= skip;
7128 }
7129 line++;
7130 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007131 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007132 /* end of string, end of loop */
7133 *line = 0;
7134 break;
7135 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007136 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007137 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007138 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007139 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007140 line++;
7141 args[++arg] = line;
7142 }
William Lallemandb2f07452015-05-12 14:27:13 +02007143 else if (dquote && *line == '$') {
7144 /* environment variables are evaluated inside double quotes */
7145 char *var_beg;
7146 char *var_end;
7147 char save_char;
7148 char *value;
7149 int val_len;
7150 int newlinesize;
7151 int braces = 0;
7152
7153 var_beg = line + 1;
7154 var_end = var_beg;
7155
7156 if (*var_beg == '{') {
7157 var_beg++;
7158 var_end++;
7159 braces = 1;
7160 }
7161
7162 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7163 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7164 err_code |= ERR_ALERT | ERR_FATAL;
7165 goto next_line; /* skip current line */
7166 }
7167
7168 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7169 var_end++;
7170
7171 save_char = *var_end;
7172 *var_end = '\0';
7173 value = getenv(var_beg);
7174 *var_end = save_char;
7175 val_len = value ? strlen(value) : 0;
7176
7177 if (braces) {
7178 if (*var_end == '}') {
7179 var_end++;
7180 braces = 0;
7181 } else {
7182 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7183 err_code |= ERR_ALERT | ERR_FATAL;
7184 goto next_line; /* skip current line */
7185 }
7186 }
7187
7188 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7189
7190 /* if not enough space in thisline */
7191 if (newlinesize > linesize) {
7192 char *newline;
7193
7194 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7195 if (newline == NULL) {
7196 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7197 err_code |= ERR_ALERT | ERR_FATAL;
7198 goto next_line; /* slip current line */
7199 }
7200 /* recompute pointers if realloc returns a new pointer */
7201 if (newline != thisline) {
7202 int i;
7203 int diff;
7204
7205 for (i = 0; i <= arg; i++) {
7206 diff = args[i] - thisline;
7207 args[i] = newline + diff;
7208 }
7209
7210 diff = var_end - thisline;
7211 var_end = newline + diff;
7212 diff = end - thisline;
7213 end = newline + diff;
7214 diff = line - thisline;
7215 line = newline + diff;
7216 thisline = newline;
7217 }
7218 linesize = newlinesize;
7219 }
7220
7221 /* insert value inside the line */
7222 memmove(line + val_len, var_end, end - var_end + 1);
7223 memcpy(line, value, val_len);
7224 end += val_len - (var_end - line);
7225 line += val_len;
7226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007227 else {
7228 line++;
7229 }
7230 }
William Lallemandb2f07452015-05-12 14:27:13 +02007231
William Lallemandf9873ba2015-05-05 17:37:14 +02007232 if (dquote) {
7233 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7234 err_code |= ERR_ALERT | ERR_FATAL;
7235 }
7236
7237 if (squote) {
7238 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7239 err_code |= ERR_ALERT | ERR_FATAL;
7240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007241
7242 /* empty line */
7243 if (!**args)
7244 continue;
7245
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007246 if (*line) {
7247 /* we had to stop due to too many args.
7248 * Let's terminate the string, print the offending part then cut the
7249 * last arg.
7250 */
7251 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7252 line++;
7253 *line = '\0';
7254
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007255 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007256 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007257 err_code |= ERR_ALERT | ERR_FATAL;
7258 args[arg] = line;
7259 }
7260
Willy Tarreau540abe42007-05-02 20:50:16 +02007261 /* zero out remaining args and ensure that at least one entry
7262 * is zeroed out.
7263 */
7264 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007265 args[arg] = line;
7266 }
7267
Willy Tarreau3842f002009-06-14 11:39:52 +02007268 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007269 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007270 char *tmp;
7271
Willy Tarreau3842f002009-06-14 11:39:52 +02007272 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007273 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007274 for (arg=0; *args[arg+1]; arg++)
7275 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007276 *tmp = '\0'; // fix the next arg to \0
7277 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007278 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007279 else if (!strcmp(args[0], "default")) {
7280 kwm = KWM_DEF;
7281 for (arg=0; *args[arg+1]; arg++)
7282 args[arg] = args[arg+1]; // shift args after inversion
7283 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007284
William Lallemand0f99e342011-10-12 17:50:54 +02007285 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7286 strcmp(args[0], "log") != 0) {
7287 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007288 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007289 }
7290
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007291 /* detect section start */
7292 list_for_each_entry(ics, &sections, list) {
7293 if (strcmp(args[0], ics->section_name) == 0) {
7294 cursection = ics->section_name;
7295 cs = ics;
7296 break;
7297 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007298 }
7299
Willy Tarreaubaaee002006-06-26 02:48:02 +02007300 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007301 if (cs)
7302 err_code |= cs->section_parser(file, linenum, args, kwm);
7303 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007304 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007305 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007306 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007307
7308 if (err_code & ERR_ABORT)
7309 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007310 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007311 free(cfg_scope);
7312 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007313 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007314 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007315 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007316 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007317}
7318
Willy Tarreau64ab6072014-09-16 12:17:36 +02007319/* This function propagates processes from frontend <from> to backend <to> so
7320 * that it is always guaranteed that a backend pointed to by a frontend is
7321 * bound to all of its processes. After that, if the target is a "listen"
7322 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007323 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324 * checked first to ensure that <to> is already bound to all processes of
7325 * <from>, there is no risk of looping and we ensure to follow the shortest
7326 * path to the destination.
7327 *
7328 * It is possible to set <to> to NULL for the first call so that the function
7329 * takes care of visiting the initial frontend in <from>.
7330 *
7331 * It is important to note that the function relies on the fact that all names
7332 * have already been resolved.
7333 */
7334void propagate_processes(struct proxy *from, struct proxy *to)
7335{
7336 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007337
7338 if (to) {
7339 /* check whether we need to go down */
7340 if (from->bind_proc &&
7341 (from->bind_proc & to->bind_proc) == from->bind_proc)
7342 return;
7343
7344 if (!from->bind_proc && !to->bind_proc)
7345 return;
7346
7347 to->bind_proc = from->bind_proc ?
7348 (to->bind_proc | from->bind_proc) : 0;
7349
7350 /* now propagate down */
7351 from = to;
7352 }
7353
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007354 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007355 return;
7356
Willy Tarreauf6b70012014-12-18 14:00:43 +01007357 if (from->state == PR_STSTOPPED)
7358 return;
7359
Willy Tarreau64ab6072014-09-16 12:17:36 +02007360 /* default_backend */
7361 if (from->defbe.be)
7362 propagate_processes(from, from->defbe.be);
7363
7364 /* use_backend */
7365 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007366 if (rule->dynamic)
7367 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007368 to = rule->be.backend;
7369 propagate_processes(from, to);
7370 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007371}
7372
Willy Tarreaubb925012009-07-23 13:36:36 +02007373/*
7374 * Returns the error code, 0 if OK, or any combination of :
7375 * - ERR_ABORT: must abort ASAP
7376 * - ERR_FATAL: we can continue parsing but not start the service
7377 * - ERR_WARN: a warning has been emitted
7378 * - ERR_ALERT: an alert has been emitted
7379 * Only the two first ones can stop processing, the two others are just
7380 * indicators.
7381 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007382int check_config_validity()
7383{
7384 int cfgerr = 0;
7385 struct proxy *curproxy = NULL;
7386 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007387 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007388 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007389 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007390 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007391 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007392
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007393 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007394 /*
7395 * Now, check for the integrity of all that we have collected.
7396 */
7397
7398 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007399 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007400
Willy Tarreau193b8c62012-11-22 00:17:38 +01007401 if (!global.tune.max_http_hdr)
7402 global.tune.max_http_hdr = MAX_HTTP_HDR;
7403
7404 if (!global.tune.cookie_len)
7405 global.tune.cookie_len = CAPTURE_LEN;
7406
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007407 if (!global.tune.requri_len)
7408 global.tune.requri_len = REQURI_LEN;
7409
Emeric Brun96fd9262017-07-05 13:33:16 +02007410 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7411
Willy Tarreau193b8c62012-11-22 00:17:38 +01007412 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7413
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007414 /* allocate pool of resolution per resolvers */
7415 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7416 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7417 /* error message is already displayed by dns_alloc_resolution_pool() */
7418 err_code |= ERR_ALERT | ERR_ABORT;
7419 goto out;
7420 }
7421 }
7422
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007423 /* Post initialisation of the users and groups lists. */
7424 err_code = userlist_postinit();
7425 if (err_code != ERR_NONE)
7426 goto out;
7427
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007428 /* first, we will invert the proxy list order */
7429 curproxy = NULL;
7430 while (proxy) {
7431 struct proxy *next;
7432
7433 next = proxy->next;
7434 proxy->next = curproxy;
7435 curproxy = proxy;
7436 if (!next)
7437 break;
7438 proxy = next;
7439 }
7440
Willy Tarreau419ead82014-09-16 13:41:21 +02007441 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007442 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007443 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007444 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007445 struct act_rule *trule;
7446 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007447 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007448 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007449 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007450
Willy Tarreau050536d2012-10-04 08:47:34 +02007451 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007452 /* proxy ID not set, use automatic numbering with first
7453 * spare entry starting with next_pxid.
7454 */
7455 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7456 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7457 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007458 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007459 next_pxid++;
7460
Willy Tarreau55ea7572007-06-17 19:56:27 +02007461
Willy Tarreaubaaee002006-06-26 02:48:02 +02007462 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007463 /* ensure we don't keep listeners uselessly bound */
7464 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007465 free((void *)curproxy->table.peers.name);
7466 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007467 continue;
7468 }
7469
Willy Tarreau102df612014-05-07 23:56:38 +02007470 /* Check multi-process mode compatibility for the current proxy */
7471
7472 if (curproxy->bind_proc) {
7473 /* an explicit bind-process was specified, let's check how many
7474 * processes remain.
7475 */
David Carliere6c39412015-07-02 07:00:17 +00007476 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007477
7478 curproxy->bind_proc &= nbits(global.nbproc);
7479 if (!curproxy->bind_proc && nbproc == 1) {
7480 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);
7481 curproxy->bind_proc = 1;
7482 }
7483 else if (!curproxy->bind_proc && nbproc > 1) {
7484 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);
7485 curproxy->bind_proc = 0;
7486 }
7487 }
7488
Willy Tarreau3d209582014-05-09 17:06:11 +02007489 /* check and reduce the bind-proc of each listener */
7490 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7491 unsigned long mask;
7492
7493 if (!bind_conf->bind_proc)
7494 continue;
7495
7496 mask = nbits(global.nbproc);
7497 if (curproxy->bind_proc)
7498 mask &= curproxy->bind_proc;
7499 /* mask cannot be null here thanks to the previous checks */
7500
David Carliere6c39412015-07-02 07:00:17 +00007501 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007502 bind_conf->bind_proc &= mask;
7503
7504 if (!bind_conf->bind_proc && nbproc == 1) {
7505 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",
7506 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7507 bind_conf->bind_proc = mask & ~(mask - 1);
7508 }
7509 else if (!bind_conf->bind_proc && nbproc > 1) {
7510 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",
7511 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7512 bind_conf->bind_proc = 0;
7513 }
7514 }
7515
Willy Tarreauff01a212009-03-15 13:46:16 +01007516 switch (curproxy->mode) {
7517 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007518 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007519 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007520 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7521 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007522 cfgerr++;
7523 }
7524
7525 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007526 Warning("config : servers will be ignored for %s '%s'.\n",
7527 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007528 break;
7529
7530 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007531 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007532 break;
7533
7534 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007535 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007536 break;
7537 }
7538
Willy Tarreauf3934b82015-08-11 11:36:45 +02007539 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7540 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7541 proxy_type_str(curproxy), curproxy->id);
7542 err_code |= ERR_WARN;
7543 }
7544
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007545 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007546 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007547 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007548 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7549 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007550 cfgerr++;
7551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007552#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007553 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007554 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7555 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007556 cfgerr++;
7557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007558#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007559 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007560 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007562 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007563 }
7564 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007565 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007566 /* If no LB algo is set in a backend, and we're not in
7567 * transparent mode, dispatch mode nor proxy mode, we
7568 * want to use balance roundrobin by default.
7569 */
7570 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7571 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007572 }
7573 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007574
Willy Tarreau1620ec32011-08-06 17:05:02 +02007575 if (curproxy->options & PR_O_DISPATCH)
7576 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7577 else if (curproxy->options & PR_O_HTTP_PROXY)
7578 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7579 else if (curproxy->options & PR_O_TRANSP)
7580 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007581
Willy Tarreau1620ec32011-08-06 17:05:02 +02007582 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7583 if (curproxy->options & PR_O_DISABLE404) {
7584 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7585 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7586 err_code |= ERR_WARN;
7587 curproxy->options &= ~PR_O_DISABLE404;
7588 }
7589 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7590 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7591 "send-state", proxy_type_str(curproxy), curproxy->id);
7592 err_code |= ERR_WARN;
7593 curproxy->options &= ~PR_O2_CHK_SNDST;
7594 }
Willy Tarreauef781042010-01-27 11:53:01 +01007595 }
7596
Simon Horman98637e52014-06-20 12:30:16 +09007597 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7598 if (!global.external_check) {
7599 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7600 curproxy->id, "option external-check");
7601 cfgerr++;
7602 }
7603 if (!curproxy->check_command) {
7604 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7605 curproxy->id, "option external-check");
7606 cfgerr++;
7607 }
7608 }
7609
Simon Horman64e34162015-02-06 11:11:57 +09007610 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007611 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7612 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007613 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7614 "'email-alert myhostname', or 'email-alert to' "
7615 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007616 "to be present).\n",
7617 proxy_type_str(curproxy), curproxy->id);
7618 err_code |= ERR_WARN;
7619 free_email_alert(curproxy);
7620 }
7621 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007622 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007623 }
7624
Simon Horman98637e52014-06-20 12:30:16 +09007625 if (curproxy->check_command) {
7626 int clear = 0;
7627 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7628 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7629 "external-check command", proxy_type_str(curproxy), curproxy->id);
7630 err_code |= ERR_WARN;
7631 clear = 1;
7632 }
7633 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007634 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007635 curproxy->id, "external-check command");
7636 cfgerr++;
7637 }
7638 if (clear) {
7639 free(curproxy->check_command);
7640 curproxy->check_command = NULL;
7641 }
7642 }
7643
7644 if (curproxy->check_path) {
7645 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7646 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7647 "external-check path", proxy_type_str(curproxy), curproxy->id);
7648 err_code |= ERR_WARN;
7649 free(curproxy->check_path);
7650 curproxy->check_path = NULL;
7651 }
7652 }
7653
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007654 /* if a default backend was specified, let's find it */
7655 if (curproxy->defbe.name) {
7656 struct proxy *target;
7657
Willy Tarreauafb39922015-05-26 12:04:09 +02007658 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007659 if (!target) {
7660 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7661 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007662 cfgerr++;
7663 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007664 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7665 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007666 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007667 } else if (target->mode != curproxy->mode &&
7668 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7669
7670 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7671 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7672 curproxy->conf.file, curproxy->conf.line,
7673 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7674 target->conf.file, target->conf.line);
7675 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007676 } else {
7677 free(curproxy->defbe.name);
7678 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007679 /* Update tot_fe_maxconn for a further fullconn's computation */
7680 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007681 /* Emit a warning if this proxy also has some servers */
7682 if (curproxy->srv) {
7683 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7684 curproxy->id);
7685 err_code |= ERR_WARN;
7686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007687 }
7688 }
7689
Emeric Brun3f783572017-01-12 11:21:28 +01007690 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7691 /* Case of listen without default backend
7692 * The curproxy will be its own default backend
7693 * so we update tot_fe_maxconn for a further
7694 * fullconn's computation */
7695 curproxy->tot_fe_maxconn += curproxy->maxconn;
7696 }
7697
Willy Tarreau55ea7572007-06-17 19:56:27 +02007698 /* find the target proxy for 'use_backend' rules */
7699 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007700 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007701 struct logformat_node *node;
7702 char *pxname;
7703
7704 /* Try to parse the string as a log format expression. If the result
7705 * of the parsing is only one entry containing a simple string, then
7706 * it's a standard string corresponding to a static rule, thus the
7707 * parsing is cancelled and be.name is restored to be resolved.
7708 */
7709 pxname = rule->be.name;
7710 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007711 curproxy->conf.args.ctx = ARGC_UBK;
7712 curproxy->conf.args.file = rule->file;
7713 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007714 err = NULL;
7715 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7716 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7717 rule->file, rule->line, pxname, err);
7718 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007719 cfgerr++;
7720 continue;
7721 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007722 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7723
7724 if (!LIST_ISEMPTY(&rule->be.expr)) {
7725 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7726 rule->dynamic = 1;
7727 free(pxname);
7728 continue;
7729 }
7730 /* simple string: free the expression and fall back to static rule */
7731 free(node->arg);
7732 free(node);
7733 }
7734
7735 rule->dynamic = 0;
7736 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007737
Willy Tarreauafb39922015-05-26 12:04:09 +02007738 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007739 if (!target) {
7740 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7741 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007742 cfgerr++;
7743 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007744 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7745 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007746 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007747 } else if (target->mode != curproxy->mode &&
7748 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7749
7750 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7751 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7752 curproxy->conf.file, curproxy->conf.line,
7753 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7754 target->conf.file, target->conf.line);
7755 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007756 } else {
7757 free((void *)rule->be.name);
7758 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007759 /* For each target of switching rules, we update
7760 * their tot_fe_maxconn, except if a previous rule point
7761 * on the same backend or on the default backend */
7762 if (rule->be.backend != curproxy->defbe.be) {
7763 struct switching_rule *swrule;
7764
7765 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7766 if (rule == swrule) {
7767 target->tot_fe_maxconn += curproxy->maxconn;
7768 break;
7769 }
7770 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7771 /* there is multiple ref of this backend */
7772 break;
7773 }
7774 }
7775 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007776 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007777 }
7778
Willy Tarreau64ab6072014-09-16 12:17:36 +02007779 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007780 list_for_each_entry(srule, &curproxy->server_rules, list) {
7781 struct server *target = findserver(curproxy, srule->srv.name);
7782
7783 if (!target) {
7784 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7785 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7786 cfgerr++;
7787 continue;
7788 }
7789 free((void *)srule->srv.name);
7790 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007791 }
7792
Emeric Brunb982a3d2010-01-04 15:45:53 +01007793 /* find the target table for 'stick' rules */
7794 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7795 struct proxy *target;
7796
Emeric Brun1d33b292010-01-04 15:47:17 +01007797 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7798 if (mrule->flags & STK_IS_STORE)
7799 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7800
Emeric Brunb982a3d2010-01-04 15:45:53 +01007801 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007802 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007803 else
7804 target = curproxy;
7805
7806 if (!target) {
7807 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7808 curproxy->id, mrule->table.name);
7809 cfgerr++;
7810 }
7811 else if (target->table.size == 0) {
7812 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7813 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7814 cfgerr++;
7815 }
Willy Tarreau12785782012-04-27 21:37:17 +02007816 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7817 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007818 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7819 cfgerr++;
7820 }
7821 else {
7822 free((void *)mrule->table.name);
7823 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007824 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007825 }
7826 }
7827
7828 /* find the target table for 'store response' rules */
7829 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7830 struct proxy *target;
7831
Emeric Brun1d33b292010-01-04 15:47:17 +01007832 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7833
Emeric Brunb982a3d2010-01-04 15:45:53 +01007834 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007835 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007836 else
7837 target = curproxy;
7838
7839 if (!target) {
7840 Alert("Proxy '%s': unable to find store table '%s'.\n",
7841 curproxy->id, mrule->table.name);
7842 cfgerr++;
7843 }
7844 else if (target->table.size == 0) {
7845 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7846 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7847 cfgerr++;
7848 }
Willy Tarreau12785782012-04-27 21:37:17 +02007849 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7850 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007851 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7852 cfgerr++;
7853 }
7854 else {
7855 free((void *)mrule->table.name);
7856 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007857 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007858 }
7859 }
7860
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007861 /* find the target table for 'tcp-request' layer 4 rules */
7862 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7863 struct proxy *target;
7864
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007865 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007866 continue;
7867
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007868 if (trule->arg.trk_ctr.table.n)
7869 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007870 else
7871 target = curproxy;
7872
7873 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007874 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007875 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007876 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007877 cfgerr++;
7878 }
7879 else if (target->table.size == 0) {
7880 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007881 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007882 cfgerr++;
7883 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007884 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007885 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007886 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007887 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007888 cfgerr++;
7889 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007890 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007891 free(trule->arg.trk_ctr.table.n);
7892 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007893 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007894 * to pass a list of counters to track and allocate them right here using
7895 * stktable_alloc_data_type().
7896 */
7897 }
7898 }
7899
Willy Tarreau620408f2016-10-21 16:37:51 +02007900 /* find the target table for 'tcp-request' layer 5 rules */
7901 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7902 struct proxy *target;
7903
7904 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7905 continue;
7906
7907 if (trule->arg.trk_ctr.table.n)
7908 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7909 else
7910 target = curproxy;
7911
7912 if (!target) {
7913 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7914 curproxy->id, trule->arg.trk_ctr.table.n,
7915 tcp_trk_idx(trule->action));
7916 cfgerr++;
7917 }
7918 else if (target->table.size == 0) {
7919 Alert("Proxy '%s': table '%s' used but not configured.\n",
7920 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7921 cfgerr++;
7922 }
7923 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7924 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7925 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7926 tcp_trk_idx(trule->action));
7927 cfgerr++;
7928 }
7929 else {
7930 free(trule->arg.trk_ctr.table.n);
7931 trule->arg.trk_ctr.table.t = &target->table;
7932 /* Note: if we decide to enhance the track-sc syntax, we may be able
7933 * to pass a list of counters to track and allocate them right here using
7934 * stktable_alloc_data_type().
7935 */
7936 }
7937 }
7938
Willy Tarreaud1f96522010-08-03 19:34:32 +02007939 /* find the target table for 'tcp-request' layer 6 rules */
7940 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7941 struct proxy *target;
7942
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007943 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007944 continue;
7945
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007946 if (trule->arg.trk_ctr.table.n)
7947 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007948 else
7949 target = curproxy;
7950
7951 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007952 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007953 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007954 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007955 cfgerr++;
7956 }
7957 else if (target->table.size == 0) {
7958 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007959 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007960 cfgerr++;
7961 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007962 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007963 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007964 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007965 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007966 cfgerr++;
7967 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007968 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007969 free(trule->arg.trk_ctr.table.n);
7970 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007971 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007972 * to pass a list of counters to track and allocate them right here using
7973 * stktable_alloc_data_type().
7974 */
7975 }
7976 }
7977
Baptiste Assmanne9544932015-11-03 23:31:35 +01007978 /* parse http-request capture rules to ensure id really exists */
7979 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7980 if (hrqrule->action != ACT_CUSTOM ||
7981 hrqrule->action_ptr != http_action_req_capture_by_id)
7982 continue;
7983
7984 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7985 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7986 curproxy->id, hrqrule->arg.capid.idx);
7987 cfgerr++;
7988 }
7989 }
7990
7991 /* parse http-response capture rules to ensure id really exists */
7992 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7993 if (hrqrule->action != ACT_CUSTOM ||
7994 hrqrule->action_ptr != http_action_res_capture_by_id)
7995 continue;
7996
7997 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7998 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7999 curproxy->id, hrqrule->arg.capid.idx);
8000 cfgerr++;
8001 }
8002 }
8003
Willy Tarreau09448f72014-06-25 18:12:15 +02008004 /* find the target table for 'http-request' layer 7 rules */
8005 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8006 struct proxy *target;
8007
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008008 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008009 continue;
8010
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008011 if (hrqrule->arg.trk_ctr.table.n)
8012 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008013 else
8014 target = curproxy;
8015
8016 if (!target) {
8017 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008018 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008019 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008020 cfgerr++;
8021 }
8022 else if (target->table.size == 0) {
8023 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008024 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008025 cfgerr++;
8026 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008027 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008028 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008029 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008030 http_trk_idx(hrqrule->action));
8031 cfgerr++;
8032 }
8033 else {
8034 free(hrqrule->arg.trk_ctr.table.n);
8035 hrqrule->arg.trk_ctr.table.t = &target->table;
8036 /* Note: if we decide to enhance the track-sc syntax, we may be able
8037 * to pass a list of counters to track and allocate them right here using
8038 * stktable_alloc_data_type().
8039 */
8040 }
8041 }
8042
8043 /* find the target table for 'http-response' layer 7 rules */
8044 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8045 struct proxy *target;
8046
8047 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8048 continue;
8049
8050 if (hrqrule->arg.trk_ctr.table.n)
8051 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8052 else
8053 target = curproxy;
8054
8055 if (!target) {
8056 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8057 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8058 http_trk_idx(hrqrule->action));
8059 cfgerr++;
8060 }
8061 else if (target->table.size == 0) {
8062 Alert("Proxy '%s': table '%s' used but not configured.\n",
8063 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8064 cfgerr++;
8065 }
8066 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8067 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8068 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8069 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008070 cfgerr++;
8071 }
8072 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008073 free(hrqrule->arg.trk_ctr.table.n);
8074 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008075 /* Note: if we decide to enhance the track-sc syntax, we may be able
8076 * to pass a list of counters to track and allocate them right here using
8077 * stktable_alloc_data_type().
8078 */
8079 }
8080 }
8081
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008082 /* move any "block" rules at the beginning of the http-request rules */
8083 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8084 /* insert block_rules into http_req_rules at the beginning */
8085 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8086 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8087 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8088 curproxy->http_req_rules.n = curproxy->block_rules.n;
8089 LIST_INIT(&curproxy->block_rules);
8090 }
8091
Emeric Brun32da3c42010-09-23 18:39:19 +02008092 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008093 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008094
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008095 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008096 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8097 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008098 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008099 break;
8100 }
8101 }
8102
8103 if (!curpeers) {
8104 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8105 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008106 free((void *)curproxy->table.peers.name);
8107 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008108 cfgerr++;
8109 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008110 else if (curpeers->state == PR_STSTOPPED) {
8111 /* silently disable this peers section */
8112 curproxy->table.peers.p = NULL;
8113 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008114 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008115 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8116 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008117 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008118 cfgerr++;
8119 }
8120 }
8121
Simon Horman9dc49962015-01-30 11:22:59 +09008122
8123 if (curproxy->email_alert.mailers.name) {
8124 struct mailers *curmailers = mailers;
8125
8126 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8127 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8128 free(curproxy->email_alert.mailers.name);
8129 curproxy->email_alert.mailers.m = curmailers;
8130 curmailers->users++;
8131 break;
8132 }
8133 }
8134
8135 if (!curmailers) {
8136 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8137 curproxy->id, curproxy->email_alert.mailers.name);
8138 free_email_alert(curproxy);
8139 cfgerr++;
8140 }
8141 }
8142
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008143 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008144 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008145 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8146 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8147 "proxy", curproxy->id);
8148 cfgerr++;
8149 goto out_uri_auth_compat;
8150 }
8151
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008152 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008153 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008154 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008155 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008156
Willy Tarreau95fa4692010-02-01 13:05:50 +01008157 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8158 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008159
8160 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008161 uri_auth_compat_req[i++] = "realm";
8162 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8163 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008164
Willy Tarreau95fa4692010-02-01 13:05:50 +01008165 uri_auth_compat_req[i++] = "unless";
8166 uri_auth_compat_req[i++] = "{";
8167 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8168 uri_auth_compat_req[i++] = "}";
8169 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008170
Willy Tarreauff011f22011-01-06 17:51:27 +01008171 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8172 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008173 cfgerr++;
8174 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008175 }
8176
Willy Tarreauff011f22011-01-06 17:51:27 +01008177 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008178
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008179 if (curproxy->uri_auth->auth_realm) {
8180 free(curproxy->uri_auth->auth_realm);
8181 curproxy->uri_auth->auth_realm = NULL;
8182 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008183
8184 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008185 }
8186out_uri_auth_compat:
8187
Dragan Dosen43885c72015-10-01 13:18:13 +02008188 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008189 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008190 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8191 if (!curproxy->conf.logformat_sd_string) {
8192 /* set the default logformat_sd_string */
8193 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8194 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008195 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008196 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008197 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008198
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008199 /* compile the log format */
8200 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008201 if (curproxy->conf.logformat_string != default_http_log_format &&
8202 curproxy->conf.logformat_string != default_tcp_log_format &&
8203 curproxy->conf.logformat_string != clf_http_log_format)
8204 free(curproxy->conf.logformat_string);
8205 curproxy->conf.logformat_string = NULL;
8206 free(curproxy->conf.lfs_file);
8207 curproxy->conf.lfs_file = NULL;
8208 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008209
8210 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8211 free(curproxy->conf.logformat_sd_string);
8212 curproxy->conf.logformat_sd_string = NULL;
8213 free(curproxy->conf.lfsd_file);
8214 curproxy->conf.lfsd_file = NULL;
8215 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008216 }
8217
Willy Tarreau62a61232013-04-12 18:13:46 +02008218 if (curproxy->conf.logformat_string) {
8219 curproxy->conf.args.ctx = ARGC_LOG;
8220 curproxy->conf.args.file = curproxy->conf.lfs_file;
8221 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008222 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008223 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008224 SMP_VAL_FE_LOG_END, &err)) {
8225 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8226 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8227 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008228 cfgerr++;
8229 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008230 curproxy->conf.args.file = NULL;
8231 curproxy->conf.args.line = 0;
8232 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008233
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008234 if (curproxy->conf.logformat_sd_string) {
8235 curproxy->conf.args.ctx = ARGC_LOGSD;
8236 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8237 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008238 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008239 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 +01008240 SMP_VAL_FE_LOG_END, &err)) {
8241 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8242 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8243 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008244 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008245 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8246 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8247 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8248 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008249 cfgerr++;
8250 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008251 curproxy->conf.args.file = NULL;
8252 curproxy->conf.args.line = 0;
8253 }
8254
Willy Tarreau62a61232013-04-12 18:13:46 +02008255 if (curproxy->conf.uniqueid_format_string) {
8256 curproxy->conf.args.ctx = ARGC_UIF;
8257 curproxy->conf.args.file = curproxy->conf.uif_file;
8258 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008259 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008260 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 +01008261 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8262 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8263 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8264 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008265 cfgerr++;
8266 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008267 curproxy->conf.args.file = NULL;
8268 curproxy->conf.args.line = 0;
8269 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008270
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008271 /* only now we can check if some args remain unresolved.
8272 * This must be done after the users and groups resolution.
8273 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008274 cfgerr += smp_resolve_args(curproxy);
8275 if (!cfgerr)
8276 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008277
Willy Tarreau2738a142006-07-08 17:28:09 +02008278 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008279 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008280 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008281 (!curproxy->timeout.connect ||
8282 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008283 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008284 " | While not properly invalid, you will certainly encounter various problems\n"
8285 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008286 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008287 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008288 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008289 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008290
Willy Tarreau1fa31262007-12-03 00:36:16 +01008291 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8292 * We must still support older configurations, so let's find out whether those
8293 * parameters have been set or must be copied from contimeouts.
8294 */
8295 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008296 if (!curproxy->timeout.tarpit ||
8297 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008298 /* tarpit timeout not set. We search in the following order:
8299 * default.tarpit, curr.connect, default.connect.
8300 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008301 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008302 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008303 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008304 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008305 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008306 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008307 }
8308 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008309 (!curproxy->timeout.queue ||
8310 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008311 /* queue timeout not set. We search in the following order:
8312 * default.queue, curr.connect, default.connect.
8313 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008314 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008315 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008316 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008317 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008318 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008319 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008320 }
8321 }
8322
Willy Tarreau1620ec32011-08-06 17:05:02 +02008323 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008324 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008325 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008326 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008327 }
8328
Willy Tarreau215663d2014-06-13 18:30:23 +02008329 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8330 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8331 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8332 proxy_type_str(curproxy), curproxy->id);
8333 err_code |= ERR_WARN;
8334 }
8335
Willy Tarreau193b8c62012-11-22 00:17:38 +01008336 /* ensure that cookie capture length is not too large */
8337 if (curproxy->capture_len >= global.tune.cookie_len) {
8338 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8339 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8340 err_code |= ERR_WARN;
8341 curproxy->capture_len = global.tune.cookie_len - 1;
8342 }
8343
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008344 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008345 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008346 curproxy->req_cap_pool = create_pool("ptrcap",
8347 curproxy->nb_req_cap * sizeof(char *),
8348 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008349 }
8350
8351 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008352 curproxy->rsp_cap_pool = create_pool("ptrcap",
8353 curproxy->nb_rsp_cap * sizeof(char *),
8354 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008355 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008356
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008357 switch (curproxy->load_server_state_from_file) {
8358 case PR_SRV_STATE_FILE_UNSPEC:
8359 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8360 break;
8361 case PR_SRV_STATE_FILE_GLOBAL:
8362 if (!global.server_state_file) {
8363 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",
8364 curproxy->id);
8365 err_code |= ERR_WARN;
8366 }
8367 break;
8368 }
8369
Willy Tarreaubaaee002006-06-26 02:48:02 +02008370 /* first, we will invert the servers list order */
8371 newsrv = NULL;
8372 while (curproxy->srv) {
8373 struct server *next;
8374
8375 next = curproxy->srv->next;
8376 curproxy->srv->next = newsrv;
8377 newsrv = curproxy->srv;
8378 if (!next)
8379 break;
8380 curproxy->srv = next;
8381 }
8382
Willy Tarreau17edc812014-01-03 12:14:34 +01008383 /* Check that no server name conflicts. This causes trouble in the stats.
8384 * We only emit a warning for the first conflict affecting each server,
8385 * in order to avoid combinatory explosion if all servers have the same
8386 * name. We do that only for servers which do not have an explicit ID,
8387 * because these IDs were made also for distinguishing them and we don't
8388 * want to annoy people who correctly manage them.
8389 */
8390 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8391 struct server *other_srv;
8392
8393 if (newsrv->puid)
8394 continue;
8395
8396 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8397 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8398 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8399 newsrv->conf.file, newsrv->conf.line,
8400 proxy_type_str(curproxy), curproxy->id,
8401 newsrv->id, other_srv->conf.line);
8402 break;
8403 }
8404 }
8405 }
8406
Willy Tarreaudd701652010-05-25 23:03:02 +02008407 /* assign automatic UIDs to servers which don't have one yet */
8408 next_id = 1;
8409 newsrv = curproxy->srv;
8410 while (newsrv != NULL) {
8411 if (!newsrv->puid) {
8412 /* server ID not set, use automatic numbering with first
8413 * spare entry starting with next_svid.
8414 */
8415 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8416 newsrv->conf.id.key = newsrv->puid = next_id;
8417 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8418 }
8419 next_id++;
8420 newsrv = newsrv->next;
8421 }
8422
Willy Tarreau20697042007-11-15 23:26:18 +01008423 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008424 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008425
Willy Tarreau62c3be22012-01-20 13:12:32 +01008426 /*
8427 * If this server supports a maxconn parameter, it needs a dedicated
8428 * tasks to fill the emptied slots when a connection leaves.
8429 * Also, resolve deferred tracking dependency if needed.
8430 */
8431 newsrv = curproxy->srv;
8432 while (newsrv != NULL) {
8433 if (newsrv->minconn > newsrv->maxconn) {
8434 /* Only 'minconn' was specified, or it was higher than or equal
8435 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8436 * this will avoid further useless expensive computations.
8437 */
8438 newsrv->maxconn = newsrv->minconn;
8439 } else if (newsrv->maxconn && !newsrv->minconn) {
8440 /* minconn was not specified, so we set it to maxconn */
8441 newsrv->minconn = newsrv->maxconn;
8442 }
8443
Willy Tarreau17d45382016-12-22 21:16:08 +01008444 /* this will also properly set the transport layer for prod and checks */
8445 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8446 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8447 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8448 }
Emeric Brun94324a42012-10-11 14:00:19 +02008449
Willy Tarreau2f075e92013-12-03 11:11:34 +01008450 /* set the check type on the server */
8451 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8452
Willy Tarreau62c3be22012-01-20 13:12:32 +01008453 if (newsrv->trackit) {
8454 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008455 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008456 char *pname, *sname;
8457
8458 pname = newsrv->trackit;
8459 sname = strrchr(pname, '/');
8460
8461 if (sname)
8462 *sname++ = '\0';
8463 else {
8464 sname = pname;
8465 pname = NULL;
8466 }
8467
8468 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008469 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008470 if (!px) {
8471 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8472 proxy_type_str(curproxy), curproxy->id,
8473 newsrv->id, pname);
8474 cfgerr++;
8475 goto next_srv;
8476 }
8477 } else
8478 px = curproxy;
8479
8480 srv = findserver(px, sname);
8481 if (!srv) {
8482 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8483 proxy_type_str(curproxy), curproxy->id,
8484 newsrv->id, sname);
8485 cfgerr++;
8486 goto next_srv;
8487 }
8488
Willy Tarreau32091232014-05-16 13:52:00 +02008489 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8490 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8491 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008492 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008493 "tracking as it does not have any check nor agent enabled.\n",
8494 proxy_type_str(curproxy), curproxy->id,
8495 newsrv->id, px->id, srv->id);
8496 cfgerr++;
8497 goto next_srv;
8498 }
8499
8500 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8501
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008502 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008503 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8504 "belongs to a tracking chain looping back to %s/%s.\n",
8505 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008506 newsrv->id, px->id, srv->id, px->id,
8507 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008508 cfgerr++;
8509 goto next_srv;
8510 }
8511
8512 if (curproxy != px &&
8513 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8514 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8515 "tracking: disable-on-404 option inconsistency.\n",
8516 proxy_type_str(curproxy), curproxy->id,
8517 newsrv->id, px->id, srv->id);
8518 cfgerr++;
8519 goto next_srv;
8520 }
8521
Willy Tarreau62c3be22012-01-20 13:12:32 +01008522 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008523 newsrv->tracknext = srv->trackers;
8524 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008525
8526 free(newsrv->trackit);
8527 newsrv->trackit = NULL;
8528 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008529
8530 /*
8531 * resolve server's resolvers name and update the resolvers pointer
8532 * accordingly
8533 */
8534 if (newsrv->resolvers_id) {
8535 struct dns_resolvers *curr_resolvers;
8536 int found;
8537
8538 found = 0;
8539 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8540 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8541 found = 1;
8542 break;
8543 }
8544 }
8545
8546 if (!found) {
8547 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8548 proxy_type_str(curproxy), curproxy->id,
8549 newsrv->id, newsrv->resolvers_id);
8550 cfgerr++;
8551 } else {
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008552 if (newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008553 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008554 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8555 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8556 proxy_type_str(curproxy), curproxy->id,
8557 newsrv->id);
8558 cfgerr++;
8559 }
8560 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008561 }
8562 }
8563 else {
8564 /* if no resolvers section associated to this server
8565 * we can clean up the associated resolution structure
8566 */
8567 if (newsrv->resolution) {
8568 free(newsrv->resolution->hostname_dn);
8569 newsrv->resolution->hostname_dn = NULL;
8570 free(newsrv->resolution);
8571 newsrv->resolution = NULL;
8572 }
8573 }
8574
Willy Tarreau62c3be22012-01-20 13:12:32 +01008575 next_srv:
8576 newsrv = newsrv->next;
8577 }
8578
Olivier Houchard4e694042017-03-14 20:01:29 +01008579 /*
8580 * Try to generate dynamic cookies for servers now.
8581 * It couldn't be done earlier, since at the time we parsed
8582 * the server line, we may not have known yet that we
8583 * should use dynamic cookies, or the secret key may not
8584 * have been provided yet.
8585 */
8586 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8587 newsrv = curproxy->srv;
8588 while (newsrv != NULL) {
8589 srv_set_dyncookie(newsrv);
8590 newsrv = newsrv->next;
8591 }
8592
8593 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008594 /* We have to initialize the server lookup mechanism depending
8595 * on what LB algorithm was choosen.
8596 */
8597
8598 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8599 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8600 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008601 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8602 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8603 init_server_map(curproxy);
8604 } else {
8605 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8606 fwrr_init_server_groups(curproxy);
8607 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008608 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008609
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008610 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008611 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8612 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8613 fwlc_init_server_tree(curproxy);
8614 } else {
8615 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8616 fas_init_server_tree(curproxy);
8617 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008618 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008619
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008620 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008621 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8622 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8623 chash_init_server_tree(curproxy);
8624 } else {
8625 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8626 init_server_map(curproxy);
8627 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008628 break;
8629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008630
8631 if (curproxy->options & PR_O_LOGASAP)
8632 curproxy->to_log &= ~LW_BYTES;
8633
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008634 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008635 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8636 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008637 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8638 proxy_type_str(curproxy), curproxy->id);
8639 err_code |= ERR_WARN;
8640 }
8641
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008642 if (curproxy->mode != PR_MODE_HTTP) {
8643 int optnum;
8644
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008645 if (curproxy->uri_auth) {
8646 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8647 proxy_type_str(curproxy), curproxy->id);
8648 err_code |= ERR_WARN;
8649 curproxy->uri_auth = NULL;
8650 }
8651
Willy Tarreaude7dc882017-03-10 11:49:21 +01008652 if (curproxy->capture_name) {
8653 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8654 proxy_type_str(curproxy), curproxy->id);
8655 err_code |= ERR_WARN;
8656 }
8657
8658 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8659 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8660 proxy_type_str(curproxy), curproxy->id);
8661 err_code |= ERR_WARN;
8662 }
8663
8664 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8665 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8666 proxy_type_str(curproxy), curproxy->id);
8667 err_code |= ERR_WARN;
8668 }
8669
8670 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8671 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8672 proxy_type_str(curproxy), curproxy->id);
8673 err_code |= ERR_WARN;
8674 }
8675
8676 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8677 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8678 proxy_type_str(curproxy), curproxy->id);
8679 err_code |= ERR_WARN;
8680 }
8681
Willy Tarreau87cf5142011-08-19 22:57:24 +02008682 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008683 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8684 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8685 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008686 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008687 }
8688
8689 if (curproxy->options & PR_O_ORGTO) {
8690 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8691 "originalto", proxy_type_str(curproxy), curproxy->id);
8692 err_code |= ERR_WARN;
8693 curproxy->options &= ~PR_O_ORGTO;
8694 }
8695
8696 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8697 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8698 (curproxy->cap & cfg_opts[optnum].cap) &&
8699 (curproxy->options & cfg_opts[optnum].val)) {
8700 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8701 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8702 err_code |= ERR_WARN;
8703 curproxy->options &= ~cfg_opts[optnum].val;
8704 }
8705 }
8706
8707 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8708 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8709 (curproxy->cap & cfg_opts2[optnum].cap) &&
8710 (curproxy->options2 & cfg_opts2[optnum].val)) {
8711 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8712 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8713 err_code |= ERR_WARN;
8714 curproxy->options2 &= ~cfg_opts2[optnum].val;
8715 }
8716 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008717
Willy Tarreau29fbe512015-08-20 19:35:14 +02008718#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008719 if (curproxy->conn_src.bind_hdr_occ) {
8720 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008721 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008722 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008723 err_code |= ERR_WARN;
8724 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008725#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008726 }
8727
Willy Tarreaubaaee002006-06-26 02:48:02 +02008728 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008729 * ensure that we're not cross-dressing a TCP server into HTTP.
8730 */
8731 newsrv = curproxy->srv;
8732 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008733 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008734 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8735 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008736 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008737 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008738
Willy Tarreau0cec3312011-10-31 13:49:26 +01008739 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8740 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8741 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8742 err_code |= ERR_WARN;
8743 }
8744
Willy Tarreauc93cd162014-05-13 15:54:22 +02008745 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008746 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8747 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8748 err_code |= ERR_WARN;
8749 }
8750
Willy Tarreau29fbe512015-08-20 19:35:14 +02008751#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008752 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8753 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008754 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 +01008755 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008756 err_code |= ERR_WARN;
8757 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008758#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008759
8760 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8761 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8762 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8763 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8764 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8765 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",
8766 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8767 err_code |= ERR_WARN;
8768 }
8769
8770
8771 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8772 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",
8773 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8774 err_code |= ERR_WARN;
8775 }
8776 }
8777
Willy Tarreau21d2af32008-02-14 20:25:24 +01008778 newsrv = newsrv->next;
8779 }
8780
Willy Tarreaue42bd962014-09-16 16:21:19 +02008781 /* check if we have a frontend with "tcp-request content" looking at L7
8782 * with no inspect-delay
8783 */
8784 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8785 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008786 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008787 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008788 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008789 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008790 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008791 break;
8792 }
8793
8794 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8795 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8796 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8797 " This means that these rules will randomly find their contents. This can be fixed by"
8798 " setting the tcp-request inspect-delay.\n",
8799 proxy_type_str(curproxy), curproxy->id);
8800 err_code |= ERR_WARN;
8801 }
8802 }
8803
Christopher Fauletd7c91962015-04-30 11:48:27 +02008804 /* Check filter configuration, if any */
8805 cfgerr += flt_check(curproxy);
8806
Willy Tarreauc1a21672009-08-16 22:37:44 +02008807 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008808 if (!curproxy->accept)
8809 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008810
Willy Tarreauc1a21672009-08-16 22:37:44 +02008811 if (curproxy->tcp_req.inspect_delay ||
8812 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008813 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008814
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008815 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008816 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008817 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008818 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008819
8820 /* both TCP and HTTP must check switching rules */
8821 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008822
8823 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008824 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008825 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8826 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 +01008827 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008828 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8829 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008830 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008831 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008832 }
8833
8834 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008835 if (curproxy->tcp_req.inspect_delay ||
8836 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8837 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8838
Emeric Brun97679e72010-09-23 17:56:44 +02008839 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8840 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8841
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008842 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008843 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008844 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008845 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008846
8847 /* If the backend does requires RDP cookie persistence, we have to
8848 * enable the corresponding analyser.
8849 */
8850 if (curproxy->options2 & PR_O2_RDPC_PRST)
8851 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008852
8853 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008854 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008855 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8856 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 +01008857 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008858 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8859 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008860 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008861 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008862 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008863 }
8864
8865 /***********************************************************/
8866 /* At this point, target names have already been resolved. */
8867 /***********************************************************/
8868
8869 /* Check multi-process mode compatibility */
8870
8871 if (global.nbproc > 1 && global.stats_fe) {
8872 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8873 unsigned long mask;
8874
8875 mask = nbits(global.nbproc);
8876 if (global.stats_fe->bind_proc)
8877 mask &= global.stats_fe->bind_proc;
8878
8879 if (bind_conf->bind_proc)
8880 mask &= bind_conf->bind_proc;
8881
8882 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008883 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008884 break;
8885 }
8886 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8887 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");
8888 }
8889 }
8890
8891 /* Make each frontend inherit bind-process from its listeners when not specified. */
8892 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8893 if (curproxy->bind_proc)
8894 continue;
8895
8896 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8897 unsigned long mask;
8898
Willy Tarreaue428b082015-05-04 21:57:58 +02008899 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008900 curproxy->bind_proc |= mask;
8901 }
8902
8903 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008904 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008905 }
8906
8907 if (global.stats_fe) {
8908 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8909 unsigned long mask;
8910
Cyril Bonté06181952016-02-24 00:14:54 +01008911 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008912 global.stats_fe->bind_proc |= mask;
8913 }
8914 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008915 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008916 }
8917
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008918 /* propagate bindings from frontends to backends. Don't do it if there
8919 * are any fatal errors as we must not call it with unresolved proxies.
8920 */
8921 if (!cfgerr) {
8922 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8923 if (curproxy->cap & PR_CAP_FE)
8924 propagate_processes(curproxy, NULL);
8925 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008926 }
8927
8928 /* Bind each unbound backend to all processes when not specified. */
8929 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8930 if (curproxy->bind_proc)
8931 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008932 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008933 }
8934
8935 /*******************************************************/
8936 /* At this step, all proxies have a non-null bind_proc */
8937 /*******************************************************/
8938
8939 /* perform the final checks before creating tasks */
8940
8941 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8942 struct listener *listener;
8943 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008944
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008945 /* Configure SSL for each bind line.
8946 * Note: if configuration fails at some point, the ->ctx member
8947 * remains NULL so that listeners can later detach.
8948 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008949 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008950 if (bind_conf->xprt->prepare_bind_conf &&
8951 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008952 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008953 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008954
Willy Tarreaue6b98942007-10-29 01:09:36 +01008955 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008956 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008957 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008958 int nbproc;
8959
8960 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008961 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008962 nbits(global.nbproc));
8963
8964 if (!nbproc) /* no intersection between listener and frontend */
8965 nbproc = 1;
8966
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008967 if (!listener->luid) {
8968 /* listener ID not set, use automatic numbering with first
8969 * spare entry starting with next_luid.
8970 */
8971 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8972 listener->conf.id.key = listener->luid = next_id;
8973 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008974 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008975 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008976
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008977 /* enable separate counters */
8978 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008979 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008980 if (!listener->name)
8981 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008982 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008983
Willy Tarreaue6b98942007-10-29 01:09:36 +01008984 if (curproxy->options & PR_O_TCP_NOLING)
8985 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008986 if (!listener->maxconn)
8987 listener->maxconn = curproxy->maxconn;
8988 if (!listener->backlog)
8989 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008990 if (!listener->maxaccept)
8991 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8992
8993 /* we want to have an optimal behaviour on single process mode to
8994 * maximize the work at once, but in multi-process we want to keep
8995 * some fairness between processes, so we target half of the max
8996 * number of events to be balanced over all the processes the proxy
8997 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8998 * used to disable the limit.
8999 */
9000 if (listener->maxaccept > 0) {
9001 if (nbproc > 1)
9002 listener->maxaccept = (listener->maxaccept + 1) / 2;
9003 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9004 }
9005
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009006 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009007 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009008 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009009 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009010
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009011 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009012 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009013
Willy Tarreau620408f2016-10-21 16:37:51 +02009014 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9015 listener->options |= LI_O_TCP_L5_RULES;
9016
Willy Tarreaude3041d2010-05-31 10:56:17 +02009017 if (curproxy->mon_mask.s_addr)
9018 listener->options |= LI_O_CHK_MONNET;
9019
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009020 /* smart accept mode is automatic in HTTP mode */
9021 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009022 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009023 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9024 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009025 }
9026
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009027 /* Release unused SSL configs */
9028 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009029 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9030 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009031 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009032
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009033 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009034 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009035 int count, maxproc = 0;
9036
9037 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009038 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009039 if (count > maxproc)
9040 maxproc = count;
9041 }
9042 /* backends have 0, frontends have 1 or more */
9043 if (maxproc != 1)
9044 Warning("Proxy '%s': in multi-process mode, stats will be"
9045 " limited to process assigned to the current request.\n",
9046 curproxy->id);
9047
Willy Tarreau102df612014-05-07 23:56:38 +02009048 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9049 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9050 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009051 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009052 }
Willy Tarreau102df612014-05-07 23:56:38 +02009053 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9054 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9055 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009056 }
9057 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009058
9059 /* create the task associated with the proxy */
9060 curproxy->task = task_new();
9061 if (curproxy->task) {
9062 curproxy->task->context = curproxy;
9063 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009064 } else {
9065 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9066 curproxy->id);
9067 cfgerr++;
9068 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009069 }
9070
Willy Tarreaufbb78422011-06-05 15:38:35 +02009071 /* automatically compute fullconn if not set. We must not do it in the
9072 * loop above because cross-references are not yet fully resolved.
9073 */
9074 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9075 /* If <fullconn> is not set, let's set it to 10% of the sum of
9076 * the possible incoming frontend's maxconns.
9077 */
9078 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009079 /* we have the sum of the maxconns in <total>. We only
9080 * keep 10% of that sum to set the default fullconn, with
9081 * a hard minimum of 1 (to avoid a divide by zero).
9082 */
Emeric Brun3f783572017-01-12 11:21:28 +01009083 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009084 if (!curproxy->fullconn)
9085 curproxy->fullconn = 1;
9086 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009087 }
9088
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009089 /*
9090 * Recount currently required checks.
9091 */
9092
9093 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9094 int optnum;
9095
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009096 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9097 if (curproxy->options & cfg_opts[optnum].val)
9098 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009099
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009100 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9101 if (curproxy->options2 & cfg_opts2[optnum].val)
9102 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009103 }
9104
Willy Tarreau0fca4832015-05-01 19:12:05 +02009105 /* compute the required process bindings for the peers */
9106 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9107 if (curproxy->table.peers.p)
9108 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9109
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009110 if (cfg_peers) {
9111 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009112 struct peer *p, *pb;
9113
Willy Tarreau1e273012015-05-01 19:15:17 +02009114 /* Remove all peers sections which don't have a valid listener,
9115 * which are not used by any table, or which are bound to more
9116 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009117 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009118 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009119 while (*last) {
9120 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009121
9122 if (curpeers->state == PR_STSTOPPED) {
9123 /* the "disabled" keyword was present */
9124 if (curpeers->peers_fe)
9125 stop_proxy(curpeers->peers_fe);
9126 curpeers->peers_fe = NULL;
9127 }
9128 else if (!curpeers->peers_fe) {
9129 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9130 curpeers->id, localpeer);
9131 }
David Carliere6c39412015-07-02 07:00:17 +00009132 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009133 /* either it's totally stopped or too much used */
9134 if (curpeers->peers_fe->bind_proc) {
9135 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009136 "running in different processes (%d different ones). "
9137 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009138 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009139 cfgerr++;
9140 }
9141 stop_proxy(curpeers->peers_fe);
9142 curpeers->peers_fe = NULL;
9143 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009144 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009145 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009146 last = &curpeers->next;
9147 continue;
9148 }
9149
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009150 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009151 p = curpeers->remote;
9152 while (p) {
9153 pb = p->next;
9154 free(p->id);
9155 free(p);
9156 p = pb;
9157 }
9158
9159 /* Destroy and unlink this curpeers section.
9160 * Note: curpeers is backed up into *last.
9161 */
9162 free(curpeers->id);
9163 curpeers = curpeers->next;
9164 free(*last);
9165 *last = curpeers;
9166 }
9167 }
9168
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009169 /* initialize stick-tables on backend capable proxies. This must not
9170 * be done earlier because the data size may be discovered while parsing
9171 * other proxies.
9172 */
9173 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9174 if (curproxy->state == PR_STSTOPPED)
9175 continue;
9176
9177 if (!stktable_init(&curproxy->table)) {
9178 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9179 cfgerr++;
9180 }
9181 }
9182
Simon Horman0d16a402015-01-30 11:22:58 +09009183 if (mailers) {
9184 struct mailers *curmailers = mailers, **last;
9185 struct mailer *m, *mb;
9186
9187 /* Remove all mailers sections which don't have a valid listener.
9188 * This can happen when a mailers section is never referenced.
9189 */
9190 last = &mailers;
9191 while (*last) {
9192 curmailers = *last;
9193 if (curmailers->users) {
9194 last = &curmailers->next;
9195 continue;
9196 }
9197
9198 Warning("Removing incomplete section 'mailers %s'.\n",
9199 curmailers->id);
9200
9201 m = curmailers->mailer_list;
9202 while (m) {
9203 mb = m->next;
9204 free(m->id);
9205 free(m);
9206 m = mb;
9207 }
9208
9209 /* Destroy and unlink this curmailers section.
9210 * Note: curmailers is backed up into *last.
9211 */
9212 free(curmailers->id);
9213 curmailers = curmailers->next;
9214 free(*last);
9215 *last = curmailers;
9216 }
9217 }
9218
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009219 /* Update server_state_file_name to backend name if backend is supposed to use
9220 * a server-state file locally defined and none has been provided */
9221 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9222 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9223 curproxy->server_state_file_name == NULL)
9224 curproxy->server_state_file_name = strdup(curproxy->id);
9225 }
9226
Willy Tarreau34eb6712011-10-24 18:15:04 +02009227 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009228 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009229 MEM_F_SHARED);
9230
Willy Tarreaubb925012009-07-23 13:36:36 +02009231 if (cfgerr > 0)
9232 err_code |= ERR_ALERT | ERR_FATAL;
9233 out:
9234 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009235}
9236
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009237/*
9238 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9239 * parsing sessions.
9240 */
9241void cfg_register_keywords(struct cfg_kw_list *kwl)
9242{
9243 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9244}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009245
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009246/*
9247 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9248 */
9249void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9250{
9251 LIST_DEL(&kwl->list);
9252 LIST_INIT(&kwl->list);
9253}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009254
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009255/* this function register new section in the haproxy configuration file.
9256 * <section_name> is the name of this new section and <section_parser>
9257 * is the called parser. If two section declaration have the same name,
9258 * only the first declared is used.
9259 */
9260int cfg_register_section(char *section_name,
9261 int (*section_parser)(const char *, int, char **, int))
9262{
9263 struct cfg_section *cs;
9264
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009265 list_for_each_entry(cs, &sections, list) {
9266 if (strcmp(cs->section_name, section_name) == 0) {
9267 Alert("register section '%s': already registered.\n", section_name);
9268 return 0;
9269 }
9270 }
9271
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009272 cs = calloc(1, sizeof(*cs));
9273 if (!cs) {
9274 Alert("register section '%s': out of memory.\n", section_name);
9275 return 0;
9276 }
9277
9278 cs->section_name = section_name;
9279 cs->section_parser = section_parser;
9280
9281 LIST_ADDQ(&sections, &cs->list);
9282
9283 return 1;
9284}
9285
Willy Tarreaubaaee002006-06-26 02:48:02 +02009286/*
David Carlier845efb52015-09-25 11:49:18 +01009287 * free all config section entries
9288 */
9289void cfg_unregister_sections(void)
9290{
9291 struct cfg_section *cs, *ics;
9292
9293 list_for_each_entry_safe(cs, ics, &sections, list) {
9294 LIST_DEL(&cs->list);
9295 free(cs);
9296 }
9297}
9298
Christopher Faulet7110b402016-10-26 11:09:44 +02009299void cfg_backup_sections(struct list *backup_sections)
9300{
9301 struct cfg_section *cs, *ics;
9302
9303 list_for_each_entry_safe(cs, ics, &sections, list) {
9304 LIST_DEL(&cs->list);
9305 LIST_ADDQ(backup_sections, &cs->list);
9306 }
9307}
9308
9309void cfg_restore_sections(struct list *backup_sections)
9310{
9311 struct cfg_section *cs, *ics;
9312
9313 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9314 LIST_DEL(&cs->list);
9315 LIST_ADDQ(&sections, &cs->list);
9316 }
9317}
9318
Willy Tarreau659fbf02016-05-26 17:55:28 +02009319__attribute__((constructor))
9320static void cfgparse_init(void)
9321{
9322 /* Register internal sections */
9323 cfg_register_section("listen", cfg_parse_listen);
9324 cfg_register_section("frontend", cfg_parse_listen);
9325 cfg_register_section("backend", cfg_parse_listen);
9326 cfg_register_section("defaults", cfg_parse_listen);
9327 cfg_register_section("global", cfg_parse_global);
9328 cfg_register_section("userlist", cfg_parse_users);
9329 cfg_register_section("peers", cfg_parse_peers);
9330 cfg_register_section("mailers", cfg_parse_mailers);
9331 cfg_register_section("namespace_list", cfg_parse_netns);
9332 cfg_register_section("resolvers", cfg_parse_resolvers);
9333}
9334
David Carlier845efb52015-09-25 11:49:18 +01009335/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009336 * Local variables:
9337 * c-indent-level: 8
9338 * c-basic-offset: 8
9339 * End:
9340 */