blob: 9b91b9048ae2f0ab9b9382d3799e8c3565b4e747 [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_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010083#include <proto/task.h>
84#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
86
Willy Tarreauf3c69202006-07-09 16:42:34 +020087/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
88 * ssl-hello-chk option to ensure that the remote server speaks SSL.
89 *
90 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
91 */
92const char sslv3_client_hello_pkt[] = {
93 "\x16" /* ContentType : 0x16 = Hanshake */
94 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
95 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
96 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
97 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
98 "\x03\x00" /* Hello Version : 0x0300 = v3 */
99 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
100 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
101 "\x00" /* Session ID length : empty (no session ID) */
102 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
103 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
104 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
105 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
106 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
107 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
108 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
109 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
110 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
111 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
112 "\x00\x38" "\x00\x39" "\x00\x3A"
113 "\x01" /* Compression Length : 0x01 = 1 byte for types */
114 "\x00" /* Compression Type : 0x00 = NULL compression */
115};
116
Willy Tarreau3842f002009-06-14 11:39:52 +0200117/* various keyword modifiers */
118enum kw_mod {
119 KWM_STD = 0, /* normal */
120 KWM_NO, /* "no" prefixed before the keyword */
121 KWM_DEF, /* "default" prefixed before the keyword */
122};
123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100124/* permit to store configuration section */
125struct cfg_section {
126 struct list list;
127 char *section_name;
128 int (*section_parser)(const char *, int, char **, int);
129};
130
131/* Used to chain configuration sections definitions. This list
132 * stores struct cfg_section
133 */
134struct list sections = LIST_HEAD_INIT(sections);
135
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100137struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138 const char *name;
139 unsigned int val;
140 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100141 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143};
144
145/* proxy->options */
146static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
149 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
150 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
151 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
152 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
153 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200155 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200156 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100157 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100158 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
159 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
160 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100162#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100164#else
165 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100166#endif
167
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100169};
170
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100171/* proxy->options2 */
172static const struct cfg_opt cfg_opts2[] =
173{
174#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100178#else
179 { "splice-request", 0, 0, 0, 0 },
180 { "splice-response", 0, 0, 0, 0 },
181 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100182#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100183 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
184 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
185 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
186 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
187 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
188 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
191 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400192 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100193 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200194 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200195 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100196 { NULL, 0, 0, 0 }
197};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198
Willy Tarreau6daf3432008-01-22 16:44:08 +0100199static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
201int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100202int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100203char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200205/* List head of all known configuration keywords */
206static struct cfg_kw_list cfg_keywords = {
207 .list = LIST_HEAD_INIT(cfg_keywords.list)
208};
209
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210/*
211 * converts <str> to a list of listeners which are dynamically allocated.
212 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
213 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
214 * - <port> is a numerical port from 1 to 65535 ;
215 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
216 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200217 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
218 * not NULL, it must be a valid pointer to either NULL or a freeable area that
219 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221int 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 +0200222{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 int port, end;
225
226 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 while (next && *next) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200229 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100230 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
232 str = next;
233 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100234 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 *next++ = 0;
236 }
237
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100238 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200239 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200240 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 if (!ss2)
242 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100245 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200246 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port || !end) {
251 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
252 goto fail;
253 }
254
Emeric Bruned760922010-10-22 17:59:25 +0200255 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200256 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100265 else if (ss2->ss_family == AF_UNSPEC) {
266 socklen_t addr_len;
267
268 /* We want to attach to an already bound fd whose number
269 * is in the addr part of ss2 when cast to sockaddr_in.
270 * Note that by definition there is a single listener.
271 * We still have to determine the address family to
272 * register the correct protocol.
273 */
274 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
275 addr_len = sizeof(*ss2);
276 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
277 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
278 goto fail;
279 }
280
281 port = end = get_host_port(ss2);
282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100284 /* OK the address looks correct */
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200285 if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
286 memprintf(err, "%s for address '%s'.\n", *err, str);
287 goto fail;
288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 } /* end while(next) */
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 fail:
293 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200294 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295}
296
William Lallemand6e62fb62015-04-28 16:55:23 +0200297/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100298 * Report an error in <msg> when there are too many arguments. This version is
299 * intended to be used by keyword parsers so that the message will be included
300 * into the general error message. The index is the current keyword in args.
301 * Return 0 if the number of argument is correct, otherwise build a message and
302 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
303 * message may also be null, it will simply not be produced (useful to check only).
304 * <msg> and <err_code> are only affected on error.
305 */
306int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
307{
308 int i;
309
310 if (!*args[index + maxarg + 1])
311 return 0;
312
313 if (msg) {
314 *msg = NULL;
315 memprintf(msg, "%s", args[0]);
316 for (i = 1; i <= index; i++)
317 memprintf(msg, "%s %s", *msg, args[i]);
318
319 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
320 }
321 if (err_code)
322 *err_code |= ERR_ALERT | ERR_FATAL;
323
324 return 1;
325}
326
327/*
328 * same as too_many_args_idx with a 0 index
329 */
330int too_many_args(int maxarg, char **args, char **msg, int *err_code)
331{
332 return too_many_args_idx(maxarg, 0, args, msg, err_code);
333}
334
335/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200336 * Report a fatal Alert when there is too much arguments
337 * The index is the current keyword in args
338 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
339 * Fill err_code with an ERR_ALERT and an ERR_FATAL
340 */
341int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
342{
343 char *kw = NULL;
344 int i;
345
346 if (!*args[index + maxarg + 1])
347 return 0;
348
349 memprintf(&kw, "%s", args[0]);
350 for (i = 1; i <= index; i++) {
351 memprintf(&kw, "%s %s", kw, args[i]);
352 }
353
354 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
355 free(kw);
356 *err_code |= ERR_ALERT | ERR_FATAL;
357 return 1;
358}
359
360/*
361 * same as alertif_too_many_args_idx with a 0 index
362 */
363int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
364{
365 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
366}
367
Willy Tarreau620408f2016-10-21 16:37:51 +0200368/* Report a warning if a rule is placed after a 'tcp-request session' rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
371int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
372{
373 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200381/* Report a warning if a rule is placed after a 'tcp-request content' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
384int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
385{
386 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
Willy Tarreau61d18892009-03-31 10:49:21 +0200394/* Report a warning if a rule is placed after a 'block' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100397int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200398{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200399 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau5002f572014-04-23 01:32:02 +0200407/* Report a warning if a rule is placed after an 'http_request' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
410int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
411{
412 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
413 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau61d18892009-03-31 10:49:21 +0200420/* Report a warning if a rule is placed after a reqrewrite rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 if (proxy->req_exp) {
426 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
433/* Report a warning if a rule is placed after a reqadd rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100436int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200437{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100438 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200439 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
440 file, line, arg);
441 return 1;
442 }
443 return 0;
444}
445
446/* Report a warning if a rule is placed after a redirect rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
451 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
453 file, line, arg);
454 return 1;
455 }
456 return 0;
457}
458
459/* Report a warning if a rule is placed after a 'use_backend' rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
464 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
Willy Tarreauee445d92014-04-23 01:39:04 +0200472/* Report a warning if a rule is placed after a 'use-server' rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
475int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
476{
477 if (!LIST_ISEMPTY(&proxy->server_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
Willy Tarreaud39ad442016-11-25 15:16:12 +0100485/* report a warning if a redirect rule is dangerously placed */
486int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200487{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100488 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200489 warnif_rule_after_use_server(proxy, file, line, arg);
490}
491
Willy Tarreaud39ad442016-11-25 15:16:12 +0100492/* report a warning if a reqadd rule is dangerously placed */
493int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200494{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100495 return warnif_rule_after_redirect(proxy, file, line, arg) ||
496 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200497}
498
Willy Tarreaud39ad442016-11-25 15:16:12 +0100499/* report a warning if a reqxxx rule is dangerously placed */
500int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200501{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100502 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
503 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200504}
505
506/* report a warning if an http-request rule is dangerously placed */
507int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
508{
Willy Tarreau61d18892009-03-31 10:49:21 +0200509 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100510 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200511}
512
Willy Tarreaud39ad442016-11-25 15:16:12 +0100513/* report a warning if a block rule is dangerously placed */
514int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200515{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100516 return warnif_rule_after_http_req(proxy, file, line, arg) ||
517 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
Willy Tarreaud39ad442016-11-25 15:16:12 +0100520/* report a warning if a "tcp request content" rule is dangerously placed */
521int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100523 return warnif_rule_after_block(proxy, file, line, arg) ||
524 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200525}
526
Willy Tarreaud39ad442016-11-25 15:16:12 +0100527/* report a warning if a "tcp request session" rule is dangerously placed */
528int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200529{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100530 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
531 warnif_misplaced_tcp_cont(proxy, file, line, arg);
532}
533
534/* report a warning if a "tcp request connection" rule is dangerously placed */
535int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
536{
537 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
538 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200539}
540
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100541/* Report it if a request ACL condition uses some keywords that are incompatible
542 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
543 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
544 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100545 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100547{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200549 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100550
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100551 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100552 return 0;
553
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554 acl = acl_cond_conflicts(cond, where);
555 if (acl) {
556 if (acl->name && *acl->name)
557 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
558 file, line, acl->name, sample_ckp_names(where));
559 else
560 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 +0200561 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 return ERR_WARN;
563 }
564 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100565 return 0;
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567 if (acl->name && *acl->name)
568 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200569 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100570 else
571 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200572 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100573 return ERR_WARN;
574}
575
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200577 * parse a line in a <global> section. Returns the error code, 0 if OK, or
578 * any combination of :
579 * - ERR_ABORT: must abort ASAP
580 * - ERR_FATAL: we can continue parsing but not start the service
581 * - ERR_WARN: a warning has been emitted
582 * - ERR_ALERT: an alert has been emitted
583 * Only the two first ones can stop processing, the two others are just
584 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200586int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587{
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200589 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590
591 if (!strcmp(args[0], "global")) { /* new section */
592 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200593 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200597 if (alertif_too_many_args(0, file, linenum, args, &err_code))
598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 global.mode |= MODE_DAEMON;
600 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200601 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200602 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200603 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200604 if (*args[1]) {
605 if (!strcmp(args[1], "exit-on-failure")) {
606 global.tune.options |= GTUNE_EXIT_ONFAILURE;
607 } else {
608 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200613 global.mode |= MODE_MWORKER;
614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200616 if (alertif_too_many_args(0, file, linenum, args, &err_code))
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 global.mode |= MODE_DEBUG;
619 }
620 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200621 if (alertif_too_many_args(0, file, linenum, args, &err_code))
622 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100623 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200625 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200626 if (alertif_too_many_args(0, file, linenum, args, &err_code))
627 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100628 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200631 if (alertif_too_many_args(0, file, linenum, args, &err_code))
632 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100633 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100635 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200636 if (alertif_too_many_args(0, file, linenum, args, &err_code))
637 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100638 global.tune.options &= ~GTUNE_USE_SPLICE;
639 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200640 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(0, file, linenum, args, &err_code))
642 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200643 global.tune.options &= ~GTUNE_USE_GAI;
644 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000645 else if (!strcmp(args[0], "noreuseport")) {
646 if (alertif_too_many_args(0, file, linenum, args, &err_code))
647 goto out;
648 global.tune.options &= ~GTUNE_USE_REUSEPORT;
649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200651 if (alertif_too_many_args(0, file, linenum, args, &err_code))
652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 global.mode |= MODE_QUIET;
654 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200655 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200656 if (alertif_too_many_args(1, file, linenum, args, &err_code))
657 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200658 if (global.tune.maxpollevents != 0) {
659 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200662 }
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200667 }
668 global.tune.maxpollevents = atol(args[1]);
669 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100670 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
672 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100673 if (global.tune.maxaccept != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100682 }
683 global.tune.maxaccept = atol(args[1]);
684 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200685 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(1, file, linenum, args, &err_code))
687 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200688 if (*(args[1]) == 0) {
689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
692 }
693 global.tune.chksize = atol(args[1]);
694 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100695 else if (!strcmp(args[0], "tune.recv_enough")) {
696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
697 goto out;
698 if (*(args[1]) == 0) {
699 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703 global.tune.recv_enough = atol(args[1]);
704 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100705 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
707 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100708 if (*(args[1]) == 0) {
709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.tune.buf_limit = atol(args[1]);
714 if (global.tune.buf_limit) {
715 if (global.tune.buf_limit < 3)
716 global.tune.buf_limit = 3;
717 if (global.tune.buf_limit <= global.tune.reserved_bufs)
718 global.tune.buf_limit = global.tune.reserved_bufs + 1;
719 }
720 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100721 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200722 if (alertif_too_many_args(1, file, linenum, args, &err_code))
723 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729 global.tune.reserved_bufs = atol(args[1]);
730 if (global.tune.reserved_bufs < 2)
731 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
733 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100734 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200735 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
737 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200744 if (global.tune.bufsize <= 0) {
745 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200749 }
750 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200751 if (alertif_too_many_args(1, file, linenum, args, &err_code))
752 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200759 if (global.tune.maxrewrite < 0) {
760 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200764 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100765 else if (!strcmp(args[0], "tune.idletimer")) {
766 unsigned int idle;
767 const char *res;
768
William Lallemand1a748ae2015-05-19 16:37:23 +0200769 if (alertif_too_many_args(1, file, linenum, args, &err_code))
770 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
776
777 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
778 if (res) {
779 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
780 file, linenum, *res, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784
785 if (idle > 65535) {
786 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790 global.tune.idle_timer = idle;
791 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100792 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
794 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100795 if (global.tune.client_rcvbuf != 0) {
796 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT;
798 goto out;
799 }
800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 global.tune.client_rcvbuf = atol(args[1]);
806 }
807 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200808 if (alertif_too_many_args(1, file, linenum, args, &err_code))
809 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100810 if (global.tune.server_rcvbuf != 0) {
811 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
812 err_code |= ERR_ALERT;
813 goto out;
814 }
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.server_rcvbuf = atol(args[1]);
821 }
822 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200823 if (alertif_too_many_args(1, file, linenum, args, &err_code))
824 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100825 if (global.tune.client_sndbuf != 0) {
826 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT;
828 goto out;
829 }
830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835 global.tune.client_sndbuf = atol(args[1]);
836 }
837 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200838 if (alertif_too_many_args(1, file, linenum, args, &err_code))
839 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100840 if (global.tune.server_sndbuf != 0) {
841 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
842 err_code |= ERR_ALERT;
843 goto out;
844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
849 }
850 global.tune.server_sndbuf = atol(args[1]);
851 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200852 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200853 if (alertif_too_many_args(1, file, linenum, args, &err_code))
854 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200855 if (*(args[1]) == 0) {
856 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860 global.tune.pipesize = atol(args[1]);
861 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100862 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200863 if (alertif_too_many_args(1, file, linenum, args, &err_code))
864 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100865 if (*(args[1]) == 0) {
866 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 global.tune.cookie_len = atol(args[1]) + 1;
871 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200872 else if (!strcmp(args[0], "tune.http.logurilen")) {
873 if (alertif_too_many_args(1, file, linenum, args, &err_code))
874 goto out;
875 if (*(args[1]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 global.tune.requri_len = atol(args[1]) + 1;
881 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200882 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200890 global.tune.max_http_hdr = atoi(args[1]);
891 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
892 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
893 file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200897 }
William Lallemandf3747832012-11-09 12:33:10 +0100898 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200899 if (alertif_too_many_args(1, file, linenum, args, &err_code))
900 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100901 if (*args[1]) {
902 global.tune.comp_maxlevel = atoi(args[1]);
903 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
904 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
905 file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 } else {
910 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
911 file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200916 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
917 if (*args[1]) {
918 global.tune.pattern_cache = atoi(args[1]);
919 if (global.tune.pattern_cache < 0) {
920 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
921 file, linenum, args[0]);
922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
924 }
925 } else {
926 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200933 if (alertif_too_many_args(1, file, linenum, args, &err_code))
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200936 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200937 err_code |= ERR_ALERT;
938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
940 if (*(args[1]) == 0) {
941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100945 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
946 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]);
947 err_code |= ERR_WARN;
948 goto out;
949 }
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200953 if (alertif_too_many_args(1, file, linenum, args, &err_code))
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200956 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200957 err_code |= ERR_ALERT;
958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100965 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
966 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]);
967 err_code |= ERR_WARN;
968 goto out;
969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
Simon Horman98637e52014-06-20 12:30:16 +0900971 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200972 if (alertif_too_many_args(0, file, linenum, args, &err_code))
973 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900974 global.external_check = 1;
975 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200976 /* user/group name handling */
977 else if (!strcmp(args[0], "user")) {
978 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200979 if (alertif_too_many_args(1, file, linenum, args, &err_code))
980 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200981 if (global.uid != 0) {
982 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200983 err_code |= ERR_ALERT;
984 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 }
986 errno = 0;
987 ha_user = getpwnam(args[1]);
988 if (ha_user != NULL) {
989 global.uid = (int)ha_user->pw_uid;
990 }
991 else {
992 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 +0200993 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200994 }
995 }
996 else if (!strcmp(args[0], "group")) {
997 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +0200998 if (alertif_too_many_args(1, file, linenum, args, &err_code))
999 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001000 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001001 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT;
1003 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001004 }
1005 errno = 0;
1006 ha_group = getgrnam(args[1]);
1007 if (ha_group != NULL) {
1008 global.gid = (int)ha_group->gr_gid;
1009 }
1010 else {
1011 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 +02001012 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001013 }
1014 }
1015 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001017 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 if (*(args[1]) == 0) {
1020 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 }
1024 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001025 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1026 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1027 file, linenum, args[0], LONGBITS, global.nbproc);
1028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
1030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 }
1032 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001033 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 if (global.maxconn != 0) {
1036 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT;
1038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 }
1040 if (*(args[1]) == 0) {
1041 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT | ERR_FATAL;
1043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 }
1045 global.maxconn = atol(args[1]);
1046#ifdef SYSTEM_MAXCONN
1047 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1048 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);
1049 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052#endif /* SYSTEM_MAXCONN */
1053 }
Emeric Brun850efd52014-01-29 12:24:34 +01001054 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001055 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1056 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 if (strcmp(args[1],"none") == 0)
1063 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1064 else if (strcmp(args[1],"required") == 0)
1065 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1066 else {
1067 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1068 err_code |= ERR_ALERT | ERR_FATAL;
1069 goto out;
1070 }
1071 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001072 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001073 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1074 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001075 if (global.cps_lim != 0) {
1076 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1077 err_code |= ERR_ALERT;
1078 goto out;
1079 }
1080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 global.cps_lim = atol(args[1]);
1086 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001087 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001088 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1089 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001090 if (global.sps_lim != 0) {
1091 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1092 err_code |= ERR_ALERT;
1093 goto out;
1094 }
1095 if (*(args[1]) == 0) {
1096 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 global.sps_lim = atol(args[1]);
1101 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001102 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001105 if (global.ssl_lim != 0) {
1106 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1107 err_code |= ERR_ALERT;
1108 goto out;
1109 }
1110 if (*(args[1]) == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
1114 }
1115 global.ssl_lim = atol(args[1]);
1116 }
William Lallemandd85f9172012-11-09 17:05:39 +01001117 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001118 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1119 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
1124 }
1125 global.comp_rate_lim = atoi(args[1]) * 1024;
1126 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001127 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001128 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1129 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001130 if (global.maxpipes != 0) {
1131 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001132 err_code |= ERR_ALERT;
1133 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001134 }
1135 if (*(args[1]) == 0) {
1136 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001137 err_code |= ERR_ALERT | ERR_FATAL;
1138 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001139 }
1140 global.maxpipes = atol(args[1]);
1141 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001142 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1144 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001145 if (*(args[1]) == 0) {
1146 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
1149 }
William Lallemande3a7d992012-11-20 11:25:20 +01001150 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001151 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001152 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001153 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1154 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001161 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001162 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001166 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001169 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 if (global.rlimit_nofile != 0) {
1172 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001173 err_code |= ERR_ALERT;
1174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 }
1176 if (*(args[1]) == 0) {
1177 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 }
1181 global.rlimit_nofile = atol(args[1]);
1182 }
1183 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001184 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 if (global.chroot != NULL) {
1187 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 err_code |= ERR_ALERT;
1189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 }
1191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
1196 global.chroot = strdup(args[1]);
1197 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001198 else if (!strcmp(args[0], "description")) {
1199 int i, len=0;
1200 char *d;
1201
1202 if (!*args[1]) {
1203 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1204 file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208
Willy Tarreau348acfe2014-04-14 15:00:39 +02001209 for (i = 1; *args[i]; i++)
1210 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001211
1212 if (global.desc)
1213 free(global.desc);
1214
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001215 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001216
Willy Tarreau348acfe2014-04-14 15:00:39 +02001217 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1218 for (i = 2; *args[i]; i++)
1219 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001220 }
1221 else if (!strcmp(args[0], "node")) {
1222 int i;
1223 char c;
1224
William Lallemand1a748ae2015-05-19 16:37:23 +02001225 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1226 goto out;
1227
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001228 for (i=0; args[1][i]; i++) {
1229 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001230 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1231 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001232 break;
1233 }
1234
1235 if (!i || args[1][i]) {
1236 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1237 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1238 file, linenum, args[0]);
1239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto out;
1241 }
1242
1243 if (global.node)
1244 free(global.node);
1245
1246 global.node = strdup(args[1]);
1247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001249 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 if (global.pidfile != NULL) {
1252 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001253 err_code |= ERR_ALERT;
1254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 }
1256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 }
1261 global.pidfile = strdup(args[1]);
1262 }
Emeric Bruned760922010-10-22 17:59:25 +02001263 else if (!strcmp(args[0], "unix-bind")) {
1264 int cur_arg = 1;
1265 while (*(args[cur_arg])) {
1266 if (!strcmp(args[cur_arg], "prefix")) {
1267 if (global.unix_bind.prefix != NULL) {
1268 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1269 err_code |= ERR_ALERT;
1270 cur_arg += 2;
1271 continue;
1272 }
1273
1274 if (*(args[cur_arg+1]) == 0) {
1275 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1280 cur_arg += 2;
1281 continue;
1282 }
1283
1284 if (!strcmp(args[cur_arg], "mode")) {
1285
1286 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1287 cur_arg += 2;
1288 continue;
1289 }
1290
1291 if (!strcmp(args[cur_arg], "uid")) {
1292
1293 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1294 cur_arg += 2;
1295 continue;
1296 }
1297
1298 if (!strcmp(args[cur_arg], "gid")) {
1299
1300 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1301 cur_arg += 2;
1302 continue;
1303 }
1304
1305 if (!strcmp(args[cur_arg], "user")) {
1306 struct passwd *user;
1307
1308 user = getpwnam(args[cur_arg + 1]);
1309 if (!user) {
1310 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1311 file, linenum, args[0], args[cur_arg + 1 ]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315
1316 global.unix_bind.ux.uid = user->pw_uid;
1317 cur_arg += 2;
1318 continue;
1319 }
1320
1321 if (!strcmp(args[cur_arg], "group")) {
1322 struct group *group;
1323
1324 group = getgrnam(args[cur_arg + 1]);
1325 if (!group) {
1326 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1327 file, linenum, args[0], args[cur_arg + 1 ]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331
1332 global.unix_bind.ux.gid = group->gr_gid;
1333 cur_arg += 2;
1334 continue;
1335 }
1336
Willy Tarreaub48f9582011-09-05 01:17:06 +02001337 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001338 file, linenum, args[0]);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342 }
William Lallemand0f99e342011-10-12 17:50:54 +02001343 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1344 /* delete previous herited or defined syslog servers */
1345 struct logsrv *back;
1346 struct logsrv *tmp;
1347
1348 if (*(args[1]) != 0) {
1349 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
1352 }
1353
1354 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1355 LIST_DEL(&tmp->list);
1356 free(tmp);
1357 }
1358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001360 struct sockaddr_storage *sk;
1361 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001362 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001363 int arg = 0;
1364 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001365
William Lallemand1a748ae2015-05-19 16:37:23 +02001366 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1367 goto out;
1368
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 if (*(args[1]) == 0 || *(args[2]) == 0) {
1370 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
William Lallemand0f99e342011-10-12 17:50:54 +02001374
Vincent Bernat02779b62016-04-03 13:48:43 +02001375 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001376
Willy Tarreau18324f52014-06-27 18:10:07 +02001377 /* just after the address, a length may be specified */
1378 if (strcmp(args[arg+2], "len") == 0) {
1379 len = atoi(args[arg+3]);
1380 if (len < 80 || len > 65535) {
1381 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1382 file, linenum, args[arg+3]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
1385 }
1386 logsrv->maxlen = len;
1387
1388 /* skip these two args */
1389 arg += 2;
1390 }
1391 else
1392 logsrv->maxlen = MAX_SYSLOG_LEN;
1393
Christopher Faulet084aa962017-08-29 16:54:41 +02001394 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001395 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001396
Dragan Dosen1322d092015-09-22 16:05:32 +02001397 /* after the length, a format may be specified */
1398 if (strcmp(args[arg+2], "format") == 0) {
1399 logsrv->format = get_log_format(args[arg+3]);
1400 if (logsrv->format < 0) {
1401 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1402 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001403 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001404 goto out;
1405 }
1406
1407 /* skip these two args */
1408 arg += 2;
1409 }
1410
David Carlier97880bb2016-04-08 10:35:26 +01001411 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1412 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001413 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001414 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001415
Willy Tarreau18324f52014-06-27 18:10:07 +02001416 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001417 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001418 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001419 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001420 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 }
1422
William Lallemand0f99e342011-10-12 17:50:54 +02001423 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001424 if (*(args[arg+3])) {
1425 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001426 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001428 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001429 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 }
1431 }
1432
William Lallemand0f99e342011-10-12 17:50:54 +02001433 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001434 if (*(args[arg+4])) {
1435 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001436 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001437 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001438 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001439 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001440 }
1441 }
1442
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001443 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001444 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001445 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001446 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001447 free(logsrv);
1448 goto out;
1449 }
1450 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001451
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001452 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001453 if (port1 != port2) {
1454 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1455 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001456 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001457 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001458 goto out;
1459 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001460
William Lallemand0f99e342011-10-12 17:50:54 +02001461 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001462 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001463 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465
William Lallemand0f99e342011-10-12 17:50:54 +02001466 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001467 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001468 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1469 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001470
1471 if (global.log_send_hostname != NULL) {
1472 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1473 err_code |= ERR_ALERT;
1474 goto out;
1475 }
1476
1477 if (*(args[1]))
1478 name = args[1];
1479 else
1480 name = hostname;
1481
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001482 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001483 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001484 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001485 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1486 if (global.server_state_base != NULL) {
1487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1488 err_code |= ERR_ALERT;
1489 goto out;
1490 }
1491
1492 if (!*(args[1])) {
1493 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1494 err_code |= ERR_FATAL;
1495 goto out;
1496 }
1497
1498 global.server_state_base = strdup(args[1]);
1499 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001500 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1501 if (global.server_state_file != NULL) {
1502 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1503 err_code |= ERR_ALERT;
1504 goto out;
1505 }
1506
1507 if (!*(args[1])) {
1508 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1509 err_code |= ERR_FATAL;
1510 goto out;
1511 }
1512
1513 global.server_state_file = strdup(args[1]);
1514 }
Kevinm48936af2010-12-22 16:08:21 +00001515 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001516 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1517 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001518 if (*(args[1]) == 0) {
1519 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
1522 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001523 chunk_destroy(&global.log_tag);
1524 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001525 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001526 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001527 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1528 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001529 if (global.spread_checks != 0) {
1530 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001531 err_code |= ERR_ALERT;
1532 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001533 }
1534 if (*(args[1]) == 0) {
1535 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001538 }
1539 global.spread_checks = atol(args[1]);
1540 if (global.spread_checks < 0 || global.spread_checks > 50) {
1541 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001545 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1546 const char *err;
1547 unsigned int val;
1548
William Lallemand1a748ae2015-05-19 16:37:23 +02001549 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1550 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001551 if (*(args[1]) == 0) {
1552 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
1555 }
1556
1557 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1558 if (err) {
1559 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1560 err_code |= ERR_ALERT | ERR_FATAL;
1561 }
1562 global.max_spread_checks = val;
1563 if (global.max_spread_checks < 0) {
1564 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1565 err_code |= ERR_ALERT | ERR_FATAL;
1566 }
1567 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001568 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1569#ifdef USE_CPU_AFFINITY
1570 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001571 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001572 unsigned long cpus = 0;
1573
1574 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001575 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001576 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001577 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001578 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001579 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001580 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001581 proc = atol(args[1]);
1582 if (proc >= 1 && proc <= LONGBITS)
1583 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001584 }
1585
1586 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001587 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",
1588 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
1593 cur_arg = 2;
1594 while (*args[cur_arg]) {
1595 unsigned int low, high;
1596
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001597 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001598 char *dash = strchr(args[cur_arg], '-');
1599
1600 low = high = str2uic(args[cur_arg]);
1601 if (dash)
1602 high = str2uic(dash + 1);
1603
1604 if (high < low) {
1605 unsigned int swap = low;
1606 low = high;
1607 high = swap;
1608 }
1609
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001610 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001611 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001612 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616
1617 while (low <= high)
1618 cpus |= 1UL << low++;
1619 }
1620 else {
1621 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1622 file, linenum, args[0], args[cur_arg]);
1623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626 cur_arg++;
1627 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001628 for (i = 0; i < LONGBITS; i++)
1629 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001630 global.cpu_map[i] = cpus;
1631#else
1632 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
1635#endif
1636 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001637 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1638 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1639 goto out;
1640
1641 if (*(args[2]) == 0) {
1642 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
1645 }
1646
1647 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1648 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1649 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653 }
1654 else if (!strcmp(args[0], "unsetenv")) {
1655 int arg;
1656
1657 if (*(args[1]) == 0) {
1658 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
1661 }
1662
1663 for (arg = 1; *args[arg]; arg++) {
1664 if (unsetenv(args[arg]) != 0) {
1665 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1666 err_code |= ERR_ALERT | ERR_FATAL;
1667 goto out;
1668 }
1669 }
1670 }
1671 else if (!strcmp(args[0], "resetenv")) {
1672 extern char **environ;
1673 char **env = environ;
1674
1675 /* args contain variable names to keep, one per argument */
1676 while (*env) {
1677 int arg;
1678
1679 /* look for current variable in among all those we want to keep */
1680 for (arg = 1; *args[arg]; arg++) {
1681 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1682 (*env)[strlen(args[arg])] == '=')
1683 break;
1684 }
1685
1686 /* delete this variable */
1687 if (!*args[arg]) {
1688 char *delim = strchr(*env, '=');
1689
1690 if (!delim || delim - *env >= trash.size) {
1691 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
1694 }
1695
1696 memcpy(trash.str, *env, delim - *env);
1697 trash.str[delim - *env] = 0;
1698
1699 if (unsetenv(trash.str) != 0) {
1700 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
1703 }
1704 }
1705 else
1706 env++;
1707 }
1708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001710 struct cfg_kw_list *kwl;
1711 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001712 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001713
1714 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1715 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1716 if (kwl->kw[index].section != CFG_GLOBAL)
1717 continue;
1718 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001719 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001720 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001721 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001723 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001724 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001725 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001726 err_code |= ERR_WARN;
1727 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001728 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001729 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001730 }
1731 }
1732 }
1733
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001737
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001739 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001740 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741}
1742
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001743void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001745 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 defproxy.mode = PR_MODE_TCP;
1747 defproxy.state = PR_STNEW;
1748 defproxy.maxconn = cfg_maxpconn;
1749 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001750 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001751 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001752
Simon Horman66183002013-02-23 10:16:43 +09001753 defproxy.defsrv.check.inter = DEF_CHKINTR;
1754 defproxy.defsrv.check.fastinter = 0;
1755 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001756 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1757 defproxy.defsrv.agent.fastinter = 0;
1758 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001759 defproxy.defsrv.check.rise = DEF_RISETIME;
1760 defproxy.defsrv.check.fall = DEF_FALLTIME;
1761 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1762 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001763 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001764 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001765 defproxy.defsrv.maxqueue = 0;
1766 defproxy.defsrv.minconn = 0;
1767 defproxy.defsrv.maxconn = 0;
1768 defproxy.defsrv.slowstart = 0;
1769 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1770 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1771 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001772
1773 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001774 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775}
1776
Willy Tarreauade5ec42010-01-28 19:33:49 +01001777
Willy Tarreau63af98d2014-05-18 08:11:41 +02001778/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1779 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1780 * ERR_FATAL in case of error.
1781 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001782static int create_cond_regex_rule(const char *file, int line,
1783 struct proxy *px, int dir, int action, int flags,
1784 const char *cmd, const char *reg, const char *repl,
1785 const char **cond_start)
1786{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001787 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001788 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001789 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001790 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001791 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001792 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001793 int cs;
1794 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001795
1796 if (px == &defproxy) {
1797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001798 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001799 goto err;
1800 }
1801
1802 if (*reg == 0) {
1803 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001804 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001805 goto err;
1806 }
1807
Christopher Faulet898566e2016-10-26 11:06:28 +02001808 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001809 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001810
Willy Tarreau5321c422010-01-28 20:35:13 +01001811 if (cond_start &&
1812 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001813 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1814 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1815 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001816 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001817 goto err;
1818 }
1819 }
1820 else if (cond_start && **cond_start) {
1821 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1822 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001823 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001824 goto err;
1825 }
1826
Willy Tarreau63af98d2014-05-18 08:11:41 +02001827 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001828 (dir == SMP_OPT_DIR_REQ) ?
1829 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1830 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1831 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001832
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001833 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001834 if (!preg) {
1835 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837 goto err;
1838 }
1839
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001840 cs = !(flags & REG_ICASE);
1841 cap = !(flags & REG_NOSUB);
1842 error = NULL;
1843 if (!regex_comp(reg, preg, cs, cap, &error)) {
1844 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1845 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001846 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001847 goto err;
1848 }
1849
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001850 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001852 if (repl && err) {
1853 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1854 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001855 ret_code |= ERR_ALERT | ERR_FATAL;
1856 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001857 }
1858
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001859 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001860 ret_code |= ERR_WARN;
1861
1862 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001863
Willy Tarreau63af98d2014-05-18 08:11:41 +02001864 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001865 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866 err:
1867 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 free(errmsg);
1869 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001870}
1871
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872/*
William Lallemand51097192015-04-14 16:35:22 +02001873 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001874 * Returns the error code, 0 if OK, or any combination of :
1875 * - ERR_ABORT: must abort ASAP
1876 * - ERR_FATAL: we can continue parsing but not start the service
1877 * - ERR_WARN: a warning has been emitted
1878 * - ERR_ALERT: an alert has been emitted
1879 * Only the two first ones can stop processing, the two others are just
1880 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001882int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1883{
1884 static struct peers *curpeers = NULL;
1885 struct peer *newpeer = NULL;
1886 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001887 struct bind_conf *bind_conf;
1888 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001889 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001890 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001891
1892 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001893 if (!*args[1]) {
1894 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001895 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001896 goto out;
1897 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001898
William Lallemand6e62fb62015-04-28 16:55:23 +02001899 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1900 goto out;
1901
Emeric Brun32da3c42010-09-23 18:39:19 +02001902 err = invalid_char(args[1]);
1903 if (err) {
1904 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1905 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001906 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001907 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001908 }
1909
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001910 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 /*
1912 * If there are two proxies with the same name only following
1913 * combinations are allowed:
1914 */
1915 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001916 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 +02001917 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001918 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001919 }
1920 }
1921
Vincent Bernat02779b62016-04-03 13:48:43 +02001922 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1924 err_code |= ERR_ALERT | ERR_ABORT;
1925 goto out;
1926 }
1927
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001928 curpeers->next = cfg_peers;
1929 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001930 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001931 curpeers->conf.line = linenum;
1932 curpeers->last_change = now.tv_sec;
1933 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001934 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001935 }
1936 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001937 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001938 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001939 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001940
1941 if (!*args[2]) {
1942 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1943 file, linenum, args[0]);
1944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
1946 }
1947
1948 err = invalid_char(args[1]);
1949 if (err) {
1950 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1951 file, linenum, *err, args[1]);
1952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
1954 }
1955
Vincent Bernat02779b62016-04-03 13:48:43 +02001956 if ((newpeer = calloc(1, sizeof(*newpeer))) == 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
1962 /* the peers are linked backwards first */
1963 curpeers->count++;
1964 newpeer->next = curpeers->remote;
1965 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001966 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001967 newpeer->conf.line = linenum;
1968
1969 newpeer->last_change = now.tv_sec;
1970 newpeer->id = strdup(args[1]);
1971
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001972 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001973 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001974 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001977 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001978
1979 proto = protocol_by_family(sk->ss_family);
1980 if (!proto || !proto->connect) {
1981 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1982 file, linenum, args[0], args[1]);
1983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
1985 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001986
1987 if (port1 != port2) {
1988 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1989 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993
Willy Tarreau2aa38802013-02-20 19:20:59 +01001994 if (!port1) {
1995 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1996 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002000
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002002 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002003 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002004 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002005
Emeric Brun32da3c42010-09-23 18:39:19 +02002006 if (strcmp(newpeer->id, localpeer) == 0) {
2007 /* Current is local peer, it define a frontend */
2008 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002009 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002010
2011 if (!curpeers->peers_fe) {
2012 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2013 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2014 err_code |= ERR_ALERT | ERR_ABORT;
2015 goto out;
2016 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002017
Willy Tarreau237250c2011-07-29 01:49:03 +02002018 init_new_proxy(curpeers->peers_fe);
2019 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002020 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002021 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2022 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002023 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002024
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002025 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002026
Willy Tarreau902636f2013-03-10 19:44:48 +01002027 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2028 if (errmsg && *errmsg) {
2029 indent_msg(&errmsg, 2);
2030 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002031 }
2032 else
2033 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2034 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 err_code |= ERR_FATAL;
2036 goto out;
2037 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002038
2039 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002040 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002041 l->maxconn = curpeers->peers_fe->maxconn;
2042 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002043 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002044 l->analysers |= curpeers->peers_fe->fe_req_ana;
2045 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002046 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2047 global.maxsock += l->maxconn;
2048 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002049 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002050 else {
2051 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2052 file, linenum, args[0], args[1],
2053 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2054 err_code |= ERR_FATAL;
2055 goto out;
2056 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002057 }
2058 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002059 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2060 curpeers->state = PR_STSTOPPED;
2061 }
2062 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2063 curpeers->state = PR_STNEW;
2064 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002065 else if (*args[0] != 0) {
2066 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
2069 }
2070
2071out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002072 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 return err_code;
2074}
2075
Baptiste Assmann325137d2015-04-13 23:40:55 +02002076/*
2077 * Parse a <resolvers> section.
2078 * Returns the error code, 0 if OK, or any combination of :
2079 * - ERR_ABORT: must abort ASAP
2080 * - ERR_FATAL: we can continue parsing but not start the service
2081 * - ERR_WARN: a warning has been emitted
2082 * - ERR_ALERT: an alert has been emitted
2083 * Only the two first ones can stop processing, the two others are just
2084 * indicators.
2085 */
2086int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2087{
2088 static struct dns_resolvers *curr_resolvers = NULL;
2089 struct dns_nameserver *newnameserver = NULL;
2090 const char *err;
2091 int err_code = 0;
2092 char *errmsg = NULL;
2093
2094 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2095 if (!*args[1]) {
2096 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2097 err_code |= ERR_ALERT | ERR_ABORT;
2098 goto out;
2099 }
2100
2101 err = invalid_char(args[1]);
2102 if (err) {
2103 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2104 file, linenum, *err, args[0], args[1]);
2105 err_code |= ERR_ALERT | ERR_ABORT;
2106 goto out;
2107 }
2108
2109 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2110 /* Error if two resolvers owns the same name */
2111 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2112 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2113 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2114 err_code |= ERR_ALERT | ERR_ABORT;
2115 }
2116 }
2117
Vincent Bernat02779b62016-04-03 13:48:43 +02002118 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002119 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2120 err_code |= ERR_ALERT | ERR_ABORT;
2121 goto out;
2122 }
2123
2124 /* default values */
2125 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2126 curr_resolvers->conf.file = strdup(file);
2127 curr_resolvers->conf.line = linenum;
2128 curr_resolvers->id = strdup(args[1]);
2129 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002130 /* default maximum response size */
2131 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002132 /* default hold period for nx, other, refuse and timeout is 30s */
2133 curr_resolvers->hold.nx = 30000;
2134 curr_resolvers->hold.other = 30000;
2135 curr_resolvers->hold.refused = 30000;
2136 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002137 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002138 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002139 curr_resolvers->hold.valid = 10000;
2140 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002141 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002142 /* default resolution pool size */
2143 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002144 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002145 LIST_INIT(&curr_resolvers->resolution.curr);
2146 LIST_INIT(&curr_resolvers->resolution.wait);
2147 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002148 }
2149 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2150 struct sockaddr_storage *sk;
2151 int port1, port2;
2152 struct protocol *proto;
2153
2154 if (!*args[2]) {
2155 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2156 file, linenum, args[0]);
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
2161 err = invalid_char(args[1]);
2162 if (err) {
2163 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2164 file, linenum, *err, args[1]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168
Baptiste Assmanna315c552015-11-02 22:55:49 +01002169 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2170 /* Error if two resolvers owns the same name */
2171 if (strcmp(newnameserver->id, args[1]) == 0) {
2172 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2173 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 }
2176 }
2177
Vincent Bernat02779b62016-04-03 13:48:43 +02002178 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002179 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2180 err_code |= ERR_ALERT | ERR_ABORT;
2181 goto out;
2182 }
2183
2184 /* the nameservers are linked backward first */
2185 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2186 curr_resolvers->count_nameservers++;
2187 newnameserver->resolvers = curr_resolvers;
2188 newnameserver->conf.file = strdup(file);
2189 newnameserver->conf.line = linenum;
2190 newnameserver->id = strdup(args[1]);
2191
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002192 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002193 if (!sk) {
2194 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
2197 }
2198
2199 proto = protocol_by_family(sk->ss_family);
2200 if (!proto || !proto->connect) {
2201 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2202 file, linenum, args[0], args[1]);
2203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
2205 }
2206
2207 if (port1 != port2) {
2208 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2209 file, linenum, args[0], args[1], args[2]);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
2212 }
2213
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002214 if (!port1 && !port2) {
2215 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2216 file, linenum, args[0], args[1]);
2217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
2219 }
2220
Baptiste Assmann325137d2015-04-13 23:40:55 +02002221 newnameserver->addr = *sk;
2222 }
2223 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2224 const char *res;
2225 unsigned int time;
2226
2227 if (!*args[2]) {
2228 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2229 file, linenum, args[0]);
2230 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2235 if (res) {
2236 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2237 file, linenum, *res, args[0]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002241 if (strcmp(args[1], "nx") == 0)
2242 curr_resolvers->hold.nx = time;
2243 else if (strcmp(args[1], "other") == 0)
2244 curr_resolvers->hold.other = time;
2245 else if (strcmp(args[1], "refused") == 0)
2246 curr_resolvers->hold.refused = time;
2247 else if (strcmp(args[1], "timeout") == 0)
2248 curr_resolvers->hold.timeout = time;
2249 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002250 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002251 else if (strcmp(args[1], "obsolete") == 0)
2252 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002253 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002254 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002255 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
2258 }
2259
2260 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002261 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002262 int i = 0;
2263
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002264 if (!*args[1]) {
2265 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2266 file, linenum, args[0]);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002270
2271 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002272 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2273 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2274 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
2278
2279 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002280 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002281 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2282 if (!*args[1]) {
2283 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2284 file, linenum, args[0]);
2285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
2287 }
2288 curr_resolvers->resolution_pool_size = atoi(args[1]);
2289 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002290 else if (strcmp(args[0], "resolve_retries") == 0) {
2291 if (!*args[1]) {
2292 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2293 file, linenum, args[0]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297 curr_resolvers->resolve_retries = atoi(args[1]);
2298 }
2299 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002300 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002301 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2302 file, linenum, args[0]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002306 else if (strcmp(args[1], "retry") == 0) {
2307 const char *res;
2308 unsigned int timeout_retry;
2309
2310 if (!*args[2]) {
2311 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2312 file, linenum, args[0], args[1]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2317 if (res) {
2318 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2319 file, linenum, *res, args[0], args[1]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323 curr_resolvers->timeout.retry = timeout_retry;
2324 }
2325 else {
2326 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2327 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002331 } /* neither "nameserver" nor "resolvers" */
2332 else if (*args[0] != 0) {
2333 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
2336 }
2337
2338 out:
2339 free(errmsg);
2340 return err_code;
2341}
Simon Horman0d16a402015-01-30 11:22:58 +09002342
2343/*
William Lallemand51097192015-04-14 16:35:22 +02002344 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002345 * Returns the error code, 0 if OK, or any combination of :
2346 * - ERR_ABORT: must abort ASAP
2347 * - ERR_FATAL: we can continue parsing but not start the service
2348 * - ERR_WARN: a warning has been emitted
2349 * - ERR_ALERT: an alert has been emitted
2350 * Only the two first ones can stop processing, the two others are just
2351 * indicators.
2352 */
2353int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2354{
2355 static struct mailers *curmailers = NULL;
2356 struct mailer *newmailer = NULL;
2357 const char *err;
2358 int err_code = 0;
2359 char *errmsg = NULL;
2360
2361 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2362 if (!*args[1]) {
2363 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2364 err_code |= ERR_ALERT | ERR_ABORT;
2365 goto out;
2366 }
2367
2368 err = invalid_char(args[1]);
2369 if (err) {
2370 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2371 file, linenum, *err, args[0], args[1]);
2372 err_code |= ERR_ALERT | ERR_ABORT;
2373 goto out;
2374 }
2375
2376 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2377 /*
2378 * If there are two proxies with the same name only following
2379 * combinations are allowed:
2380 */
2381 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002382 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 +09002383 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002385 }
2386 }
2387
Vincent Bernat02779b62016-04-03 13:48:43 +02002388 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2390 err_code |= ERR_ALERT | ERR_ABORT;
2391 goto out;
2392 }
2393
2394 curmailers->next = mailers;
2395 mailers = curmailers;
2396 curmailers->conf.file = strdup(file);
2397 curmailers->conf.line = linenum;
2398 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002399 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2400 * But need enough time so that timeouts don't occur
2401 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002402 }
2403 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2404 struct sockaddr_storage *sk;
2405 int port1, port2;
2406 struct protocol *proto;
2407
2408 if (!*args[2]) {
2409 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2410 file, linenum, args[0]);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414
2415 err = invalid_char(args[1]);
2416 if (err) {
2417 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2418 file, linenum, *err, args[1]);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
2422
Vincent Bernat02779b62016-04-03 13:48:43 +02002423 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002424 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2425 err_code |= ERR_ALERT | ERR_ABORT;
2426 goto out;
2427 }
2428
2429 /* the mailers are linked backwards first */
2430 curmailers->count++;
2431 newmailer->next = curmailers->mailer_list;
2432 curmailers->mailer_list = newmailer;
2433 newmailer->mailers = curmailers;
2434 newmailer->conf.file = strdup(file);
2435 newmailer->conf.line = linenum;
2436
2437 newmailer->id = strdup(args[1]);
2438
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002439 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002440 if (!sk) {
2441 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
2444 }
2445
2446 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002447 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2448 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002449 file, linenum, args[0], args[1]);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
2454 if (port1 != port2) {
2455 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2456 file, linenum, args[0], args[1], args[2]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460
2461 if (!port1) {
2462 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2463 file, linenum, args[0], args[1], args[2]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467
2468 newmailer->addr = *sk;
2469 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002470 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002471 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002472 }
2473 else if (strcmp(args[0], "timeout") == 0) {
2474 if (!*args[1]) {
2475 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2476 file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480 else if (strcmp(args[1], "mail") == 0) {
2481 const char *res;
2482 unsigned int timeout_mail;
2483 if (!*args[2]) {
2484 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2485 file, linenum, args[0], args[1]);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
2489 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2490 if (res) {
2491 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2492 file, linenum, *res, args[0]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496 if (timeout_mail <= 0) {
2497 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501 curmailers->timeout.mail = timeout_mail;
2502 } else {
2503 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2504 file, linenum, args[0], args[1]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508 }
Simon Horman0d16a402015-01-30 11:22:58 +09002509 else if (*args[0] != 0) {
2510 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514
2515out:
2516 free(errmsg);
2517 return err_code;
2518}
2519
Simon Horman9dc49962015-01-30 11:22:59 +09002520static void free_email_alert(struct proxy *p)
2521{
2522 free(p->email_alert.mailers.name);
2523 p->email_alert.mailers.name = NULL;
2524 free(p->email_alert.from);
2525 p->email_alert.from = NULL;
2526 free(p->email_alert.to);
2527 p->email_alert.to = NULL;
2528 free(p->email_alert.myhostname);
2529 p->email_alert.myhostname = NULL;
2530}
2531
Willy Tarreau3842f002009-06-14 11:39:52 +02002532int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533{
2534 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002535 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002536 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002537 int rc;
2538 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002539 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002540 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002541 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002542 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002543 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545 if (!strcmp(args[0], "listen"))
2546 rc = PR_CAP_LISTEN;
2547 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002548 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002549 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002550 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002551 else
2552 rc = PR_CAP_NONE;
2553
2554 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 if (!*args[1]) {
2556 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002557 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_ABORT;
2560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002562
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002563 err = invalid_char(args[1]);
2564 if (err) {
2565 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2566 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002568 }
2569
Willy Tarreau8f50b682015-05-26 11:45:02 +02002570 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2571 if (curproxy) {
2572 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2573 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2574 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002576 }
2577
Vincent Bernat02779b62016-04-03 13:48:43 +02002578 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_ABORT;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002583
Willy Tarreau97cb7802010-01-03 20:23:58 +01002584 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 curproxy->next = proxy;
2586 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002587 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2588 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002589 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002592 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593
William Lallemand6e62fb62015-04-28 16:55:23 +02002594 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2595 if (curproxy->cap & PR_CAP_FE)
2596 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
2599
2600 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002601 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002602 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002603
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002606 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002607 curproxy->no_options = defproxy.no_options;
2608 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002609 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002610 curproxy->except_net = defproxy.except_net;
2611 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002612 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002613 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002615 if (defproxy.fwdfor_hdr_len) {
2616 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2617 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2618 }
2619
Willy Tarreaub86db342009-11-30 11:50:16 +01002620 if (defproxy.orgto_hdr_len) {
2621 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2622 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2623 }
2624
Mark Lamourinec2247f02012-01-04 13:02:01 -05002625 if (defproxy.server_id_hdr_len) {
2626 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2627 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2628 }
2629
Willy Tarreau977b8e42006-12-29 14:19:17 +01002630 if (curproxy->cap & PR_CAP_FE) {
2631 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002632 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002633 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634
2635 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002636 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2637 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638
2639 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002643 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002644 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 curproxy->fullconn = defproxy.fullconn;
2646 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002647 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002648 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002650 if (defproxy.check_req) {
2651 curproxy->check_req = calloc(1, defproxy.check_len);
2652 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2653 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002656 if (defproxy.expect_str) {
2657 curproxy->expect_str = strdup(defproxy.expect_str);
2658 if (defproxy.expect_regex) {
2659 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002660 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2661 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002662 }
2663 }
2664
Willy Tarreau67402132012-05-31 20:40:20 +02002665 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666 if (defproxy.cookie_name)
2667 curproxy->cookie_name = strdup(defproxy.cookie_name);
2668 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002669
2670 if (defproxy.dyncookie_key)
2671 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002672 if (defproxy.cookie_domain)
2673 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002674
Willy Tarreau31936852010-10-06 16:59:56 +02002675 if (defproxy.cookie_maxidle)
2676 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2677
2678 if (defproxy.cookie_maxlife)
2679 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2680
Emeric Brun647caf12009-06-30 17:57:00 +02002681 if (defproxy.rdp_cookie_name)
2682 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2683 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2684
Willy Tarreau01732802007-11-01 22:48:15 +01002685 if (defproxy.url_param_name)
2686 curproxy->url_param_name = strdup(defproxy.url_param_name);
2687 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002688
Benoitaffb4812009-03-25 13:02:10 +01002689 if (defproxy.hh_name)
2690 curproxy->hh_name = strdup(defproxy.hh_name);
2691 curproxy->hh_len = defproxy.hh_len;
2692 curproxy->hh_match_domain = defproxy.hh_match_domain;
2693
Willy Tarreauef9a3602012-12-08 22:29:20 +01002694 if (defproxy.conn_src.iface_name)
2695 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2696 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002697 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002698#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002699 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002700#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002701 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002704 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 if (defproxy.capture_name)
2706 curproxy->capture_name = strdup(defproxy.capture_name);
2707 curproxy->capture_namelen = defproxy.capture_namelen;
2708 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710
Willy Tarreau977b8e42006-12-29 14:19:17 +01002711 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002712 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002713 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002714 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002715 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002716 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 curproxy->mon_net = defproxy.mon_net;
2718 curproxy->mon_mask = defproxy.mon_mask;
2719 if (defproxy.monitor_uri)
2720 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2721 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002722 if (defproxy.defbe.name)
2723 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002724
2725 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002726 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2727 if (curproxy->conf.logformat_string &&
2728 curproxy->conf.logformat_string != default_http_log_format &&
2729 curproxy->conf.logformat_string != default_tcp_log_format &&
2730 curproxy->conf.logformat_string != clf_http_log_format)
2731 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2732
2733 if (defproxy.conf.lfs_file) {
2734 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2735 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2736 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002737
2738 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2739 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2740 if (curproxy->conf.logformat_sd_string &&
2741 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2742 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2743
2744 if (defproxy.conf.lfsd_file) {
2745 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2746 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2747 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002748 }
2749
2750 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002751 curproxy->timeout.connect = defproxy.timeout.connect;
2752 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002753 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002754 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002755 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002756 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002757 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002758 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002759 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002760 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 }
2762
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002764 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002765
2766 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002767 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002768 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002769 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002770 LIST_INIT(&node->list);
2771 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2772 }
2773
Willy Tarreau62a61232013-04-12 18:13:46 +02002774 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2775 if (curproxy->conf.uniqueid_format_string)
2776 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2777
Dragan Dosen43885c72015-10-01 13:18:13 +02002778 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002779
Willy Tarreau62a61232013-04-12 18:13:46 +02002780 if (defproxy.conf.uif_file) {
2781 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2782 curproxy->conf.uif_line = defproxy.conf.uif_line;
2783 }
William Lallemanda73203e2012-03-12 12:48:57 +01002784
2785 /* copy default header unique id */
2786 if (defproxy.header_unique_id)
2787 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2788
William Lallemand82fe75c2012-10-23 10:25:10 +02002789 /* default compression options */
2790 if (defproxy.comp != NULL) {
2791 curproxy->comp = calloc(1, sizeof(struct comp));
2792 curproxy->comp->algos = defproxy.comp->algos;
2793 curproxy->comp->types = defproxy.comp->types;
2794 }
2795
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002797 curproxy->conf.used_listener_id = EB_ROOT;
2798 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002799
Simon Horman98637e52014-06-20 12:30:16 +09002800 if (defproxy.check_path)
2801 curproxy->check_path = strdup(defproxy.check_path);
2802 if (defproxy.check_command)
2803 curproxy->check_command = strdup(defproxy.check_command);
2804
Simon Horman9dc49962015-01-30 11:22:59 +09002805 if (defproxy.email_alert.mailers.name)
2806 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2807 if (defproxy.email_alert.from)
2808 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2809 if (defproxy.email_alert.to)
2810 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2811 if (defproxy.email_alert.myhostname)
2812 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002813 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002814 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002815
Willy Tarreau93893792009-07-23 13:19:11 +02002816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817 }
2818 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2819 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002820 /* FIXME-20070101: we should do this too at the end of the
2821 * config parsing to free all default values.
2822 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002823 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2824 err_code |= ERR_ABORT;
2825 goto out;
2826 }
2827
Willy Tarreaua534fea2008-08-03 12:19:50 +02002828 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002829 free(defproxy.check_command);
2830 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002831 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002832 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002833 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002834 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002835 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002836 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002837 free(defproxy.capture_name);
2838 free(defproxy.monitor_uri);
2839 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002840 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002841 free(defproxy.fwdfor_hdr_name);
2842 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002843 free(defproxy.orgto_hdr_name);
2844 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002845 free(defproxy.server_id_hdr_name);
2846 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002847 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002848 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002849 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002850 free(defproxy.expect_regex);
2851 defproxy.expect_regex = NULL;
2852 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002853
Willy Tarreau62a61232013-04-12 18:13:46 +02002854 if (defproxy.conf.logformat_string != default_http_log_format &&
2855 defproxy.conf.logformat_string != default_tcp_log_format &&
2856 defproxy.conf.logformat_string != clf_http_log_format)
2857 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002858
Willy Tarreau62a61232013-04-12 18:13:46 +02002859 free(defproxy.conf.uniqueid_format_string);
2860 free(defproxy.conf.lfs_file);
2861 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002862 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002863 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002864
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002865 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2866 free(defproxy.conf.logformat_sd_string);
2867 free(defproxy.conf.lfsd_file);
2868
Willy Tarreaua534fea2008-08-03 12:19:50 +02002869 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002870 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002871
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 /* we cannot free uri_auth because it might already be used */
2873 init_default_instance();
2874 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002875 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2876 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
2880 else if (curproxy == NULL) {
2881 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002885
2886 /* update the current file and line being parsed */
2887 curproxy->conf.args.file = curproxy->conf.file;
2888 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889
2890 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002891 if (!strcmp(args[0], "server") ||
2892 !strcmp(args[0], "default-server") ||
2893 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002894 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2895 if (err_code & ERR_FATAL)
2896 goto out;
2897 }
2898 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002899 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002900 int cur_arg;
2901
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 if (curproxy == &defproxy) {
2903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909
Willy Tarreau24709282013-03-10 21:32:12 +01002910 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002911 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002916
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002917 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002918
2919 /* use default settings for unix sockets */
2920 bind_conf->ux.uid = global.unix_bind.ux.uid;
2921 bind_conf->ux.gid = global.unix_bind.ux.gid;
2922 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002923
2924 /* NOTE: the following line might create several listeners if there
2925 * are comma-separated IPs or port ranges. So all further processing
2926 * will have to be applied to all listeners created after last_listen.
2927 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002928 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2929 if (errmsg && *errmsg) {
2930 indent_msg(&errmsg, 2);
2931 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002932 }
2933 else
2934 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2935 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002939
Willy Tarreau4348fad2012-09-20 16:48:07 +02002940 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2941 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002942 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002943 }
2944
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002945 cur_arg = 2;
2946 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002947 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002948 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002949 char *err;
2950
Willy Tarreau26982662012-09-12 23:17:10 +02002951 kw = bind_find_kw(args[cur_arg]);
2952 if (kw) {
2953 char *err = NULL;
2954 int code;
2955
2956 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002957 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2958 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002959 cur_arg += 1 + kw->skip ;
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
Willy Tarreau4348fad2012-09-20 16:48:07 +02002964 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002965 err_code |= code;
2966
2967 if (code) {
2968 if (err && *err) {
2969 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002970 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002971 }
2972 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002973 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002975 if (code & ERR_FATAL) {
2976 free(err);
2977 cur_arg += 1 + kw->skip;
2978 goto out;
2979 }
2980 }
2981 free(err);
2982 cur_arg += 1 + kw->skip;
2983 continue;
2984 }
2985
Willy Tarreau8638f482012-09-18 18:01:17 +02002986 err = NULL;
2987 if (!bind_dumped) {
2988 bind_dump_kws(&err);
2989 indent_msg(&err, 4);
2990 bind_dumped = 1;
2991 }
2992
2993 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2994 file, linenum, args[0], args[1], args[cur_arg],
2995 err ? " Registered keywords :" : "", err ? err : "");
2996 free(err);
2997
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003000 }
Willy Tarreau93893792009-07-23 13:19:11 +02003001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 }
3003 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003004 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003012
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 /* flush useless bits */
3014 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003017 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003018 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020
William Lallemanddf1425a2015-04-28 20:17:49 +02003021 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3022 goto out;
3023
Willy Tarreau1c47f852006-07-09 08:22:27 +02003024 if (!*args[1]) {
3025 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003029 }
3030
Willy Tarreaua534fea2008-08-03 12:19:50 +02003031 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003032 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003033 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003034 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003035 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3036
Willy Tarreau93893792009-07-23 13:19:11 +02003037 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3041 goto out;
3042
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3044 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3045 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3046 else {
3047 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003052 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003053 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003054
3055 if (curproxy == &defproxy) {
3056 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003060 }
3061
William Lallemanddf1425a2015-04-28 20:17:49 +02003062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3063 goto out;
3064
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065 if (!*args[1]) {
3066 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003070 }
3071
3072 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003073 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003074 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003075
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003076 if (curproxy->uuid <= 0) {
3077 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003078 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003081 }
3082
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003083 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3084 if (node) {
3085 struct proxy *target = container_of(node, struct proxy, conf.id);
3086 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3087 file, linenum, proxy_type_str(curproxy), curproxy->id,
3088 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003093 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003094 else if (!strcmp(args[0], "description")) {
3095 int i, len=0;
3096 char *d;
3097
Cyril Bonté99ed3272010-01-24 23:29:44 +01003098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3100 file, linenum, args[0]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 if (!*args[1]) {
3106 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3107 file, linenum, args[0]);
3108 return -1;
3109 }
3110
Willy Tarreau348acfe2014-04-14 15:00:39 +02003111 for (i = 1; *args[i]; i++)
3112 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003113
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003114 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003115 curproxy->desc = d;
3116
Willy Tarreau348acfe2014-04-14 15:00:39 +02003117 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3118 for (i = 2; *args[i]; i++)
3119 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003120
3121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003123 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 curproxy->state = PR_STSTOPPED;
3126 }
3127 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003128 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 curproxy->state = PR_STNEW;
3131 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003132 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3133 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003134 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003135
3136 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003137 unsigned int low, high;
3138
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003139 if (strcmp(args[cur_arg], "all") == 0) {
3140 set = 0;
3141 break;
3142 }
3143 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003144 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003145 }
3146 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003147 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003148 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003149 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003150 char *dash = strchr(args[cur_arg], '-');
3151
3152 low = high = str2uic(args[cur_arg]);
3153 if (dash)
3154 high = str2uic(dash + 1);
3155
3156 if (high < low) {
3157 unsigned int swap = low;
3158 low = high;
3159 high = swap;
3160 }
3161
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003162 if (low < 1 || high > LONGBITS) {
3163 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3164 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003167 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003168 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003169 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003170 }
3171 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003172 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3173 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003176 }
3177 cur_arg++;
3178 }
3179 curproxy->bind_proc = set;
3180 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003181 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003182 if (curproxy == &defproxy) {
3183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003186 }
3187
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003188 err = invalid_char(args[1]);
3189 if (err) {
3190 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3191 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003193 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003194 }
3195
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003196 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003197 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3198 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003201 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003202 }
3203 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3204
3205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3206 err_code |= ERR_WARN;
3207
3208 if (*(args[1]) == 0) {
3209 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3210 file, linenum, args[0]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214 free(curproxy->dyncookie_key);
3215 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3218 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219
Willy Tarreau977b8e42006-12-29 14:19:17 +01003220 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003222
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 if (*(args[1]) == 0) {
3224 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3225 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003229
Willy Tarreau67402132012-05-31 20:40:20 +02003230 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003231 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003232 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003233 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 curproxy->cookie_name = strdup(args[1]);
3235 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003236
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 cur_arg = 2;
3238 while (*(args[cur_arg])) {
3239 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003240 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
3242 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003243 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003246 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
3248 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003249 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
3251 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003252 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003254 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003255 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003258 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003260 else if (!strcmp(args[cur_arg], "httponly")) {
3261 curproxy->ck_opts |= PR_CK_HTTPONLY;
3262 }
3263 else if (!strcmp(args[cur_arg], "secure")) {
3264 curproxy->ck_opts |= PR_CK_SECURE;
3265 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003266 else if (!strcmp(args[cur_arg], "domain")) {
3267 if (!*args[cur_arg + 1]) {
3268 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3269 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003272 }
3273
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003274 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003275 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003276 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3277 " dots nor does not start with a dot."
3278 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003279 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003280 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003281 }
3282
3283 err = invalid_domainchar(args[cur_arg + 1]);
3284 if (err) {
3285 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3286 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003289 }
3290
Willy Tarreau68a897b2009-12-03 23:28:34 +01003291 if (!curproxy->cookie_domain) {
3292 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3293 } else {
3294 /* one domain was already specified, add another one by
3295 * building the string which will be returned along with
3296 * the cookie.
3297 */
3298 char *new_ptr;
3299 int new_len = strlen(curproxy->cookie_domain) +
3300 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3301 new_ptr = malloc(new_len);
3302 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3303 free(curproxy->cookie_domain);
3304 curproxy->cookie_domain = new_ptr;
3305 }
Willy Tarreau31936852010-10-06 16:59:56 +02003306 cur_arg++;
3307 }
3308 else if (!strcmp(args[cur_arg], "maxidle")) {
3309 unsigned int maxidle;
3310 const char *res;
3311
3312 if (!*args[cur_arg + 1]) {
3313 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3314 file, linenum, args[cur_arg]);
3315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
3317 }
3318
3319 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3320 if (res) {
3321 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3322 file, linenum, *res, args[cur_arg]);
3323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
3325 }
3326 curproxy->cookie_maxidle = maxidle;
3327 cur_arg++;
3328 }
3329 else if (!strcmp(args[cur_arg], "maxlife")) {
3330 unsigned int maxlife;
3331 const char *res;
3332
3333 if (!*args[cur_arg + 1]) {
3334 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3335 file, linenum, args[cur_arg]);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
3338 }
3339
3340 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3341 if (res) {
3342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3343 file, linenum, *res, args[cur_arg]);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346 }
3347 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003348 cur_arg++;
3349 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003350 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003351
3352 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3353 err_code |= ERR_WARN;
3354 curproxy->ck_opts |= PR_CK_DYNAMIC;
3355 }
3356
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003358 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 +02003359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
3363 cur_arg++;
3364 }
Willy Tarreau67402132012-05-31 20:40:20 +02003365 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3367 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
3370
Willy Tarreau67402132012-05-31 20:40:20 +02003371 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3373 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003376
Willy Tarreau67402132012-05-31 20:40:20 +02003377 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003378 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3379 file, linenum);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003383 else if (!strcmp(args[0], "email-alert")) {
3384 if (*(args[1]) == 0) {
3385 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3386 file, linenum, args[0]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
3390
3391 if (!strcmp(args[1], "from")) {
3392 if (*(args[1]) == 0) {
3393 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3394 file, linenum, args[1]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398 free(curproxy->email_alert.from);
3399 curproxy->email_alert.from = strdup(args[2]);
3400 }
3401 else if (!strcmp(args[1], "mailers")) {
3402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3404 file, linenum, args[1]);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408 free(curproxy->email_alert.mailers.name);
3409 curproxy->email_alert.mailers.name = strdup(args[2]);
3410 }
3411 else if (!strcmp(args[1], "myhostname")) {
3412 if (*(args[1]) == 0) {
3413 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3414 file, linenum, args[1]);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
3418 free(curproxy->email_alert.myhostname);
3419 curproxy->email_alert.myhostname = strdup(args[2]);
3420 }
Simon Horman64e34162015-02-06 11:11:57 +09003421 else if (!strcmp(args[1], "level")) {
3422 curproxy->email_alert.level = get_log_level(args[2]);
3423 if (curproxy->email_alert.level < 0) {
3424 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3425 file, linenum, args[1], args[2]);
3426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
3428 }
3429 }
Simon Horman9dc49962015-01-30 11:22:59 +09003430 else if (!strcmp(args[1], "to")) {
3431 if (*(args[1]) == 0) {
3432 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3433 file, linenum, args[1]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437 free(curproxy->email_alert.to);
3438 curproxy->email_alert.to = strdup(args[2]);
3439 }
3440 else {
3441 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3442 file, linenum, args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
Simon Horman64e34162015-02-06 11:11:57 +09003446 /* Indicate that the email_alert is at least partially configured */
3447 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003448 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003449 else if (!strcmp(args[0], "external-check")) {
3450 if (*(args[1]) == 0) {
3451 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3452 file, linenum, args[0]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
3457 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003458 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003459 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003460 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003461 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3462 file, linenum, args[1]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 free(curproxy->check_command);
3467 curproxy->check_command = strdup(args[2]);
3468 }
3469 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003470 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003471 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003472 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003473 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3474 file, linenum, args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 free(curproxy->check_path);
3479 curproxy->check_path = strdup(args[2]);
3480 }
3481 else {
3482 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3483 file, linenum, args[1]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003488 else if (!strcmp(args[0], "persist")) { /* persist */
3489 if (*(args[1]) == 0) {
3490 Alert("parsing [%s:%d] : missing persist method.\n",
3491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003494 }
3495
3496 if (!strncmp(args[1], "rdp-cookie", 10)) {
3497 curproxy->options2 |= PR_O2_RDPC_PRST;
3498
Emeric Brunb982a3d2010-01-04 15:45:53 +01003499 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003500 const char *beg, *end;
3501
3502 beg = args[1] + 11;
3503 end = strchr(beg, ')');
3504
William Lallemanddf1425a2015-04-28 20:17:49 +02003505 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3506 goto out;
3507
Emeric Brun647caf12009-06-30 17:57:00 +02003508 if (!end || end == beg) {
3509 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3510 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003513 }
3514
3515 free(curproxy->rdp_cookie_name);
3516 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3517 curproxy->rdp_cookie_len = end-beg;
3518 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003519 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003520 free(curproxy->rdp_cookie_name);
3521 curproxy->rdp_cookie_name = strdup("msts");
3522 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3523 }
3524 else { /* syntax */
3525 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3526 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003529 }
3530 }
3531 else {
3532 Alert("parsing [%s:%d] : unknown persist method.\n",
3533 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003536 }
3537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003539 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
3542 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003543 else if (!strcmp(args[0], "load-server-state-from-file")) {
3544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3545 err_code |= ERR_WARN;
3546 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3547 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3548 }
3549 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3550 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3551 }
3552 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3553 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3554 }
3555 else {
3556 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3557 file, linenum, args[0], args[1]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561 }
3562 else if (!strcmp(args[0], "server-state-file-name")) {
3563 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3564 err_code |= ERR_WARN;
3565 if (*(args[1]) == 0) {
3566 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3567 file, linenum, args[0]);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
3571 else if (!strcmp(args[1], "use-backend-name"))
3572 curproxy->server_state_file_name = strdup(curproxy->id);
3573 else
3574 curproxy->server_state_file_name = strdup(args[1]);
3575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003577 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003579
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003581 if (curproxy == &defproxy) {
3582 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
3585 }
3586
William Lallemand1a748ae2015-05-19 16:37:23 +02003587 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3588 goto out;
3589
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 if (*(args[4]) == 0) {
3591 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003596 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 curproxy->capture_name = strdup(args[2]);
3598 curproxy->capture_namelen = strlen(curproxy->capture_name);
3599 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 curproxy->to_log |= LW_COOKIE;
3601 }
3602 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3603 struct cap_hdr *hdr;
3604
3605 if (curproxy == &defproxy) {
3606 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 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
3610
William Lallemand1a748ae2015-05-19 16:37:23 +02003611 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3612 goto out;
3613
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3615 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3616 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 }
3620
Vincent Bernat02779b62016-04-03 13:48:43 +02003621 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 hdr->next = curproxy->req_cap;
3623 hdr->name = strdup(args[3]);
3624 hdr->namelen = strlen(args[3]);
3625 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003626 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 hdr->index = curproxy->nb_req_cap++;
3628 curproxy->req_cap = hdr;
3629 curproxy->to_log |= LW_REQHDR;
3630 }
3631 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3632 struct cap_hdr *hdr;
3633
3634 if (curproxy == &defproxy) {
3635 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 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
3639
William Lallemand1a748ae2015-05-19 16:37:23 +02003640 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3641 goto out;
3642
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3644 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3645 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003649 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 hdr->next = curproxy->rsp_cap;
3651 hdr->name = strdup(args[3]);
3652 hdr->namelen = strlen(args[3]);
3653 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003654 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 hdr->index = curproxy->nb_rsp_cap++;
3656 curproxy->rsp_cap = hdr;
3657 curproxy->to_log |= LW_RSPHDR;
3658 }
3659 else {
3660 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3661 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 }
3665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003667 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003669
William Lallemanddf1425a2015-04-28 20:17:49 +02003670 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3671 goto out;
3672
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 if (*(args[1]) == 0) {
3674 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679 curproxy->conn_retries = atol(args[1]);
3680 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003681 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003682 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003683
3684 if (curproxy == &defproxy) {
3685 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689
Willy Tarreau20b0de52012-12-24 15:45:22 +01003690 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003691 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003692 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3693 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3694 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3695 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003696 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 +01003697 file, linenum, args[0]);
3698 err_code |= ERR_WARN;
3699 }
3700
Willy Tarreauff011f22011-01-06 17:51:27 +01003701 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003702
Willy Tarreauff011f22011-01-06 17:51:27 +01003703 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003704 err_code |= ERR_ALERT | ERR_ABORT;
3705 goto out;
3706 }
3707
Willy Tarreau5002f572014-04-23 01:32:02 +02003708 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003709 err_code |= warnif_cond_conflicts(rule->cond,
3710 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3711 file, linenum);
3712
Willy Tarreauff011f22011-01-06 17:51:27 +01003713 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003714 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003715 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003716 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003717
3718 if (curproxy == &defproxy) {
3719 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723
3724 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003725 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003726 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3727 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003728 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3729 file, linenum, args[0]);
3730 err_code |= ERR_WARN;
3731 }
3732
3733 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3734
3735 if (!rule) {
3736 err_code |= ERR_ALERT | ERR_ABORT;
3737 goto out;
3738 }
3739
3740 err_code |= warnif_cond_conflicts(rule->cond,
3741 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3742 file, linenum);
3743
3744 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3745 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003746 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3747 /* set the header name and length into the proxy structure */
3748 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3749 err_code |= ERR_WARN;
3750
3751 if (!*args[1]) {
3752 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3753 file, linenum, args[0]);
3754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
3756 }
3757
3758 /* set the desired header name */
3759 free(curproxy->server_id_hdr_name);
3760 curproxy->server_id_hdr_name = strdup(args[1]);
3761 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3762 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003763 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003764 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003765
Willy Tarreaub099aca2008-10-12 17:26:37 +02003766 if (curproxy == &defproxy) {
3767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003770 }
3771
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003772 /* emulate "block" using "http-request block". Since these rules are supposed to
3773 * be processed before all http-request rules, we put them into their own list
3774 * and will insert them at the end.
3775 */
3776 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3777 if (!rule) {
3778 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003779 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003780 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003781 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3782 err_code |= warnif_cond_conflicts(rule->cond,
3783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3784 file, linenum);
3785 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003786
3787 if (!already_warned(WARN_BLOCK_DEPRECATED))
3788 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]);
3789
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003790 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003791 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003792 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003793
Cyril Bonté99ed3272010-01-24 23:29:44 +01003794 if (curproxy == &defproxy) {
3795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
Willy Tarreaube4653b2015-05-28 15:26:58 +02003800 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003801 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3802 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003805 }
3806
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003807 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003808 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003809 err_code |= warnif_cond_conflicts(rule->cond,
3810 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3811 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003812 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003813 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003814 struct switching_rule *rule;
3815
Willy Tarreaub099aca2008-10-12 17:26:37 +02003816 if (curproxy == &defproxy) {
3817 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003820 }
3821
Willy Tarreau55ea7572007-06-17 19:56:27 +02003822 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003824
3825 if (*(args[1]) == 0) {
3826 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003829 }
3830
Willy Tarreauf51658d2014-04-23 01:21:56 +02003831 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3832 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3833 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3834 file, linenum, errmsg);
3835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
3837 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003838
Willy Tarreauf51658d2014-04-23 01:21:56 +02003839 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003840 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003841 else if (*args[2]) {
3842 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3843 file, linenum, args[2]);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003847
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003848 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003849 if (!rule) {
3850 Alert("Out of memory error.\n");
3851 goto out;
3852 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003853 rule->cond = cond;
3854 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003855 rule->line = linenum;
3856 rule->file = strdup(file);
3857 if (!rule->file) {
3858 Alert("Out of memory error.\n");
3859 goto out;
3860 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003861 LIST_INIT(&rule->list);
3862 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3863 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003864 else if (strcmp(args[0], "use-server") == 0) {
3865 struct server_rule *rule;
3866
3867 if (curproxy == &defproxy) {
3868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
3871 }
3872
3873 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3874 err_code |= ERR_WARN;
3875
3876 if (*(args[1]) == 0) {
3877 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
3880 }
3881
3882 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3883 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3884 file, linenum, args[0]);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003889 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3890 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3891 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003896 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003897
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003898 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003899 rule->cond = cond;
3900 rule->srv.name = strdup(args[1]);
3901 LIST_INIT(&rule->list);
3902 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3903 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3904 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003905 else if ((!strcmp(args[0], "force-persist")) ||
3906 (!strcmp(args[0], "ignore-persist"))) {
3907 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003908
3909 if (curproxy == &defproxy) {
3910 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914
3915 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3916 err_code |= ERR_WARN;
3917
Willy Tarreauef6494c2010-01-28 17:12:36 +01003918 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003919 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3920 file, linenum, args[0]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003925 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3926 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3927 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003932 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3933 * where force-persist is applied.
3934 */
3935 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003936
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003937 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003938 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003939 if (!strcmp(args[0], "force-persist")) {
3940 rule->type = PERSIST_TYPE_FORCE;
3941 } else {
3942 rule->type = PERSIST_TYPE_IGNORE;
3943 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003944 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003945 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003946 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003947 else if (!strcmp(args[0], "stick-table")) {
3948 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003949 struct proxy *other;
3950
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003951 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003952 if (other) {
3953 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3954 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003958
Emeric Brun32da3c42010-09-23 18:39:19 +02003959 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003960 curproxy->table.type = (unsigned int)-1;
3961 while (*args[myidx]) {
3962 const char *err;
3963
3964 if (strcmp(args[myidx], "size") == 0) {
3965 myidx++;
3966 if (!*(args[myidx])) {
3967 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3968 file, linenum, args[myidx-1]);
3969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
3971 }
3972 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3973 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3974 file, linenum, *err, args[myidx-1]);
3975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
3977 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003978 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003979 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003980 else if (strcmp(args[myidx], "peers") == 0) {
3981 myidx++;
Godbach50523162013-12-11 19:48:57 +08003982 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003983 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3984 file, linenum, args[myidx-1]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Godbach50523162013-12-11 19:48:57 +08003987 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003988 curproxy->table.peers.name = strdup(args[myidx++]);
3989 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003990 else if (strcmp(args[myidx], "expire") == 0) {
3991 myidx++;
3992 if (!*(args[myidx])) {
3993 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3994 file, linenum, args[myidx-1]);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3999 if (err) {
4000 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4001 file, linenum, *err, args[myidx-1]);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004005 if (val > INT_MAX) {
4006 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4007 file, linenum, val);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004011 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004012 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004013 }
4014 else if (strcmp(args[myidx], "nopurge") == 0) {
4015 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004016 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 }
4018 else if (strcmp(args[myidx], "type") == 0) {
4019 myidx++;
4020 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4021 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4022 file, linenum, args[myidx]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004026 /* myidx already points to next arg */
4027 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004028 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004029 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004030 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004031
4032 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004033 nw = args[myidx];
4034 while (*nw) {
4035 /* the "store" keyword supports a comma-separated list */
4036 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004037 sa = NULL; /* store arg */
4038 while (*nw && *nw != ',') {
4039 if (*nw == '(') {
4040 *nw = 0;
4041 sa = ++nw;
4042 while (*nw != ')') {
4043 if (!*nw) {
4044 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4045 file, linenum, args[0], cw);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049 nw++;
4050 }
4051 *nw = '\0';
4052 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004053 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004054 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004055 if (*nw)
4056 *nw++ = '\0';
4057 type = stktable_get_data_type(cw);
4058 if (type < 0) {
4059 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4060 file, linenum, args[0], cw);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
Willy Tarreauac782882010-06-20 10:41:54 +02004064
4065 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4066 switch (err) {
4067 case PE_NONE: break;
4068 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004069 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4070 file, linenum, args[0], cw);
4071 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004072 break;
4073
4074 case PE_ARG_MISSING:
4075 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4076 file, linenum, args[0], cw);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079
4080 case PE_ARG_NOT_USED:
4081 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4082 file, linenum, args[0], cw);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085
4086 default:
4087 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4088 file, linenum, args[0], cw);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004091 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004092 }
4093 myidx++;
4094 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004095 else {
4096 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4097 file, linenum, args[myidx]);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004100 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004101 }
4102
4103 if (!curproxy->table.size) {
4104 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4105 file, linenum);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109
4110 if (curproxy->table.type == (unsigned int)-1) {
4111 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4112 file, linenum);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
4115 }
4116 }
4117 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004119 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 int myidx = 0;
4121 const char *name = NULL;
4122 int flags;
4123
4124 if (curproxy == &defproxy) {
4125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129
4130 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4131 err_code |= ERR_WARN;
4132 goto out;
4133 }
4134
4135 myidx++;
4136 if ((strcmp(args[myidx], "store") == 0) ||
4137 (strcmp(args[myidx], "store-request") == 0)) {
4138 myidx++;
4139 flags = STK_IS_STORE;
4140 }
4141 else if (strcmp(args[myidx], "store-response") == 0) {
4142 myidx++;
4143 flags = STK_IS_STORE | STK_ON_RSP;
4144 }
4145 else if (strcmp(args[myidx], "match") == 0) {
4146 myidx++;
4147 flags = STK_IS_MATCH;
4148 }
4149 else if (strcmp(args[myidx], "on") == 0) {
4150 myidx++;
4151 flags = STK_IS_MATCH | STK_IS_STORE;
4152 }
4153 else {
4154 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
4158
4159 if (*(args[myidx]) == 0) {
4160 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004165 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004166 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004168 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
4171 }
4172
4173 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004174 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4175 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4176 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004177 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004178 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004179 goto out;
4180 }
4181 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004182 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4183 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4184 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004185 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004186 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004187 goto out;
4188 }
4189 }
4190
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004191 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004192 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004193
Emeric Brunb982a3d2010-01-04 15:45:53 +01004194 if (strcmp(args[myidx], "table") == 0) {
4195 myidx++;
4196 name = args[myidx++];
4197 }
4198
Willy Tarreauef6494c2010-01-28 17:12:36 +01004199 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004200 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4201 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4202 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004203 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004204 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 goto out;
4206 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004208 else if (*(args[myidx])) {
4209 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4210 file, linenum, args[0], args[myidx]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004212 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004213 goto out;
4214 }
Emeric Brun97679e72010-09-23 17:56:44 +02004215 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004216 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004217 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004218 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004219
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004220 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004221 rule->cond = cond;
4222 rule->expr = expr;
4223 rule->flags = flags;
4224 rule->table.name = name ? strdup(name) : NULL;
4225 LIST_INIT(&rule->list);
4226 if (flags & STK_ON_RSP)
4227 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4228 else
4229 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 else if (!strcmp(args[0], "stats")) {
4232 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4233 curproxy->uri_auth = NULL; /* we must detach from the default config */
4234
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004235 if (!*args[1]) {
4236 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004237 } else if (!strcmp(args[1], "admin")) {
4238 struct stats_admin_rule *rule;
4239
4240 if (curproxy == &defproxy) {
4241 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 }
4245
4246 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4248 err_code |= ERR_ALERT | ERR_ABORT;
4249 goto out;
4250 }
4251
4252 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4253 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4254 file, linenum, args[0], args[1]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004258 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4259 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4260 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
4264
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004265 err_code |= warnif_cond_conflicts(cond,
4266 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4267 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004268
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004269 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004270 rule->cond = cond;
4271 LIST_INIT(&rule->list);
4272 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 } else if (!strcmp(args[1], "uri")) {
4274 if (*(args[2]) == 0) {
4275 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_ABORT;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 }
4283 } else if (!strcmp(args[1], "realm")) {
4284 if (*(args[2]) == 0) {
4285 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_ABORT;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004293 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004294 unsigned interval;
4295
4296 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4297 if (err) {
4298 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4299 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004302 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_ABORT;
4305 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004306 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004307 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004308 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004309
4310 if (curproxy == &defproxy) {
4311 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315
4316 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4317 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4318 err_code |= ERR_ALERT | ERR_ABORT;
4319 goto out;
4320 }
4321
Willy Tarreauff011f22011-01-06 17:51:27 +01004322 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004323 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004324 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4325 file, linenum, args[0]);
4326 err_code |= ERR_WARN;
4327 }
4328
Willy Tarreauff011f22011-01-06 17:51:27 +01004329 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004330
Willy Tarreauff011f22011-01-06 17:51:27 +01004331 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004332 err_code |= ERR_ALERT | ERR_ABORT;
4333 goto out;
4334 }
4335
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004336 err_code |= warnif_cond_conflicts(rule->cond,
4337 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4338 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004339 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004340
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 } else if (!strcmp(args[1], "auth")) {
4342 if (*(args[2]) == 0) {
4343 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_ABORT;
4349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 }
4351 } else if (!strcmp(args[1], "scope")) {
4352 if (*(args[2]) == 0) {
4353 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_ABORT;
4359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 }
4361 } else if (!strcmp(args[1], "enable")) {
4362 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4363 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004364 err_code |= ERR_ALERT | ERR_ABORT;
4365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004366 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004367 } else if (!strcmp(args[1], "hide-version")) {
4368 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4369 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004370 err_code |= ERR_ALERT | ERR_ABORT;
4371 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004372 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004373 } else if (!strcmp(args[1], "show-legends")) {
4374 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4375 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4376 err_code |= ERR_ALERT | ERR_ABORT;
4377 goto out;
4378 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004379 } else if (!strcmp(args[1], "show-node")) {
4380
4381 if (*args[2]) {
4382 int i;
4383 char c;
4384
4385 for (i=0; args[2][i]; i++) {
4386 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004387 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4388 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004389 break;
4390 }
4391
4392 if (!i || args[2][i]) {
4393 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4394 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4395 file, linenum, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399 }
4400
4401 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4403 err_code |= ERR_ALERT | ERR_ABORT;
4404 goto out;
4405 }
4406 } else if (!strcmp(args[1], "show-desc")) {
4407 char *desc = NULL;
4408
4409 if (*args[2]) {
4410 int i, len=0;
4411 char *d;
4412
Willy Tarreau348acfe2014-04-14 15:00:39 +02004413 for (i = 2; *args[i]; i++)
4414 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004415
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004416 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004417
Willy Tarreau348acfe2014-04-14 15:00:39 +02004418 d += snprintf(d, desc + len - d, "%s", args[2]);
4419 for (i = 3; *args[i]; i++)
4420 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004421 }
4422
4423 if (!*args[2] && !global.desc)
4424 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4425 file, linenum, args[1]);
4426 else {
4427 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4428 free(desc);
4429 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4430 err_code |= ERR_ALERT | ERR_ABORT;
4431 goto out;
4432 }
4433 free(desc);
4434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004436stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004437 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 +01004438 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
4442 }
4443 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004444 int optnum;
4445
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004446 if (*(args[1]) == '\0') {
4447 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004452
4453 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4454 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004455 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4456 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4457 file, linenum, cfg_opts[optnum].name);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004461 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4462 goto out;
4463
Willy Tarreau93893792009-07-23 13:19:11 +02004464 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4465 err_code |= ERR_WARN;
4466 goto out;
4467 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004468
Willy Tarreau3842f002009-06-14 11:39:52 +02004469 curproxy->no_options &= ~cfg_opts[optnum].val;
4470 curproxy->options &= ~cfg_opts[optnum].val;
4471
4472 switch (kwm) {
4473 case KWM_STD:
4474 curproxy->options |= cfg_opts[optnum].val;
4475 break;
4476 case KWM_NO:
4477 curproxy->no_options |= cfg_opts[optnum].val;
4478 break;
4479 case KWM_DEF: /* already cleared */
4480 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004481 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004482
Willy Tarreau93893792009-07-23 13:19:11 +02004483 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004484 }
4485 }
4486
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004487 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4488 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004489 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4490 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4491 file, linenum, cfg_opts2[optnum].name);
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004495 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4496 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004497 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4498 err_code |= ERR_WARN;
4499 goto out;
4500 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004501
Willy Tarreau3842f002009-06-14 11:39:52 +02004502 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4503 curproxy->options2 &= ~cfg_opts2[optnum].val;
4504
4505 switch (kwm) {
4506 case KWM_STD:
4507 curproxy->options2 |= cfg_opts2[optnum].val;
4508 break;
4509 case KWM_NO:
4510 curproxy->no_options2 |= cfg_opts2[optnum].val;
4511 break;
4512 case KWM_DEF: /* already cleared */
4513 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004514 }
Willy Tarreau93893792009-07-23 13:19:11 +02004515 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004516 }
4517 }
4518
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004519 /* HTTP options override each other. They can be cancelled using
4520 * "no option xxx" which only switches to default mode if the mode
4521 * was this one (useful for cancelling options set in defaults
4522 * sections).
4523 */
4524 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004525 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4526 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004527 if (kwm == KWM_STD) {
4528 curproxy->options &= ~PR_O_HTTP_MODE;
4529 curproxy->options |= PR_O_HTTP_PCL;
4530 goto out;
4531 }
4532 else if (kwm == KWM_NO) {
4533 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4534 curproxy->options &= ~PR_O_HTTP_MODE;
4535 goto out;
4536 }
4537 }
4538 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004539 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4540 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004541 if (kwm == KWM_STD) {
4542 curproxy->options &= ~PR_O_HTTP_MODE;
4543 curproxy->options |= PR_O_HTTP_FCL;
4544 goto out;
4545 }
4546 else if (kwm == KWM_NO) {
4547 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4548 curproxy->options &= ~PR_O_HTTP_MODE;
4549 goto out;
4550 }
4551 }
4552 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004553 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4554 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004555 if (kwm == KWM_STD) {
4556 curproxy->options &= ~PR_O_HTTP_MODE;
4557 curproxy->options |= PR_O_HTTP_SCL;
4558 goto out;
4559 }
4560 else if (kwm == KWM_NO) {
4561 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4562 curproxy->options &= ~PR_O_HTTP_MODE;
4563 goto out;
4564 }
4565 }
4566 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004567 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4568 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004569 if (kwm == KWM_STD) {
4570 curproxy->options &= ~PR_O_HTTP_MODE;
4571 curproxy->options |= PR_O_HTTP_KAL;
4572 goto out;
4573 }
4574 else if (kwm == KWM_NO) {
4575 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4576 curproxy->options &= ~PR_O_HTTP_MODE;
4577 goto out;
4578 }
4579 }
4580 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004581 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4582 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004583 if (kwm == KWM_STD) {
4584 curproxy->options &= ~PR_O_HTTP_MODE;
4585 curproxy->options |= PR_O_HTTP_TUN;
4586 goto out;
4587 }
4588 else if (kwm == KWM_NO) {
4589 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4590 curproxy->options &= ~PR_O_HTTP_MODE;
4591 goto out;
4592 }
4593 }
4594
Joseph Lynch726ab712015-05-11 23:25:34 -07004595 /* Redispatch can take an integer argument that control when the
4596 * resispatch occurs. All values are relative to the retries option.
4597 * This can be cancelled using "no option xxx".
4598 */
4599 if (strcmp(args[1], "redispatch") == 0) {
4600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4601 err_code |= ERR_WARN;
4602 goto out;
4603 }
4604
4605 curproxy->no_options &= ~PR_O_REDISP;
4606 curproxy->options &= ~PR_O_REDISP;
4607
4608 switch (kwm) {
4609 case KWM_STD:
4610 curproxy->options |= PR_O_REDISP;
4611 curproxy->redispatch_after = -1;
4612 if(*args[2]) {
4613 curproxy->redispatch_after = atol(args[2]);
4614 }
4615 break;
4616 case KWM_NO:
4617 curproxy->no_options |= PR_O_REDISP;
4618 curproxy->redispatch_after = 0;
4619 break;
4620 case KWM_DEF: /* already cleared */
4621 break;
4622 }
4623 goto out;
4624 }
4625
Willy Tarreau3842f002009-06-14 11:39:52 +02004626 if (kwm != KWM_STD) {
4627 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004628 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004631 }
4632
Emeric Brun3a058f32009-06-30 18:26:00 +02004633 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004634 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004636 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004637 if (*(args[2]) != '\0') {
4638 if (!strcmp(args[2], "clf")) {
4639 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004640 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004641 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004642 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004645 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004646 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4647 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004648 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004649 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4650 char *oldlogformat = "log-format";
4651 char *clflogformat = "";
4652
4653 if (curproxy->conf.logformat_string == default_http_log_format)
4654 oldlogformat = "option httplog";
4655 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4656 oldlogformat = "option tcplog";
4657 else if (curproxy->conf.logformat_string == clf_http_log_format)
4658 oldlogformat = "option httplog clf";
4659 if (logformat == clf_http_log_format)
4660 clflogformat = " clf";
4661 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4662 file, linenum, clflogformat, oldlogformat);
4663 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004664 if (curproxy->conf.logformat_string != default_http_log_format &&
4665 curproxy->conf.logformat_string != default_tcp_log_format &&
4666 curproxy->conf.logformat_string != clf_http_log_format)
4667 free(curproxy->conf.logformat_string);
4668 curproxy->conf.logformat_string = logformat;
4669
4670 free(curproxy->conf.lfs_file);
4671 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4672 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004673 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004674 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004675 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4676 char *oldlogformat = "log-format";
4677
4678 if (curproxy->conf.logformat_string == default_http_log_format)
4679 oldlogformat = "option httplog";
4680 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4681 oldlogformat = "option tcplog";
4682 else if (curproxy->conf.logformat_string == clf_http_log_format)
4683 oldlogformat = "option httplog clf";
4684 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4685 file, linenum, oldlogformat);
4686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004688 if (curproxy->conf.logformat_string != default_http_log_format &&
4689 curproxy->conf.logformat_string != default_tcp_log_format &&
4690 curproxy->conf.logformat_string != clf_http_log_format)
4691 free(curproxy->conf.logformat_string);
4692 curproxy->conf.logformat_string = default_tcp_log_format;
4693
4694 free(curproxy->conf.lfs_file);
4695 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4696 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004697
4698 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4699 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004702 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004703 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004705
William Lallemanddf1425a2015-04-28 20:17:49 +02004706 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4707 goto out;
4708
Willy Tarreau13943ab2006-12-31 00:24:10 +01004709 if (curproxy->cap & PR_CAP_FE)
4710 curproxy->options |= PR_O_TCP_CLI_KA;
4711 if (curproxy->cap & PR_CAP_BE)
4712 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 }
4714 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_WARN;
4717
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004721 curproxy->options2 &= ~PR_O2_CHK_ANY;
4722 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 if (!*args[2]) { /* no argument */
4724 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4725 curproxy->check_len = strlen(DEF_CHECK_REQ);
4726 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004727 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004728 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004730 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004732 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 if (*args[4])
4734 reqlen += strlen(args[4]);
4735 else
4736 reqlen += strlen("HTTP/1.0");
4737
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004738 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004740 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004742 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4743 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004744 }
4745 else if (!strcmp(args[1], "ssl-hello-chk")) {
4746 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004749
Willy Tarreaua534fea2008-08-03 12:19:50 +02004750 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004751 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004752 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004753 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004754
4755 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
Willy Tarreau23677902007-05-08 23:50:35 +02004758 else if (!strcmp(args[1], "smtpchk")) {
4759 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004760 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004761 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004762 curproxy->options2 &= ~PR_O2_CHK_ANY;
4763 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004764
4765 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4766 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4767 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4768 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4769 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4770 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004771 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004772 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4773 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4774 } else {
4775 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4776 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4777 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4778 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4779 }
4780 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004781 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4782 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004783 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004784 else if (!strcmp(args[1], "pgsql-check")) {
4785 /* use PostgreSQL request to check servers' health */
4786 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4787 err_code |= ERR_WARN;
4788
4789 free(curproxy->check_req);
4790 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004791 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004792 curproxy->options2 |= PR_O2_PGSQL_CHK;
4793
4794 if (*(args[2])) {
4795 int cur_arg = 2;
4796
4797 while (*(args[cur_arg])) {
4798 if (strcmp(args[cur_arg], "user") == 0) {
4799 char * packet;
4800 uint32_t packet_len;
4801 uint32_t pv;
4802
4803 /* suboption header - needs additional argument for it */
4804 if (*(args[cur_arg+1]) == 0) {
4805 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4806 file, linenum, args[0], args[1], args[cur_arg]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
4810
4811 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4812 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4813 pv = htonl(0x30000); /* protocol version 3.0 */
4814
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004815 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004816
4817 memcpy(packet + 4, &pv, 4);
4818
4819 /* copy "user" */
4820 memcpy(packet + 8, "user", 4);
4821
4822 /* copy username */
4823 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4824
4825 free(curproxy->check_req);
4826 curproxy->check_req = packet;
4827 curproxy->check_len = packet_len;
4828
4829 packet_len = htonl(packet_len);
4830 memcpy(packet, &packet_len, 4);
4831 cur_arg += 2;
4832 } else {
4833 /* unknown suboption - catchall */
4834 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4835 file, linenum, args[0], args[1]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
4839 } /* end while loop */
4840 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004841 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4842 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004843 }
4844
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004845 else if (!strcmp(args[1], "redis-check")) {
4846 /* use REDIS PING request to check servers' health */
4847 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4848 err_code |= ERR_WARN;
4849
4850 free(curproxy->check_req);
4851 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004852 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004853 curproxy->options2 |= PR_O2_REDIS_CHK;
4854
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004855 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004856 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4857 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004858
4859 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4860 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004861 }
4862
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004863 else if (!strcmp(args[1], "mysql-check")) {
4864 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4866 err_code |= ERR_WARN;
4867
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004868 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004869 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004870 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004871 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004872
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004873 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004874 * const char mysql40_client_auth_pkt[] = {
4875 * "\x0e\x00\x00" // packet length
4876 * "\x01" // packet number
4877 * "\x00\x00" // client capabilities
4878 * "\x00\x00\x01" // max packet
4879 * "haproxy\x00" // username (null terminated string)
4880 * "\x00" // filler (always 0x00)
4881 * "\x01\x00\x00" // packet length
4882 * "\x00" // packet number
4883 * "\x01" // COM_QUIT command
4884 * };
4885 */
4886
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004887 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4888 * const char mysql41_client_auth_pkt[] = {
4889 * "\x0e\x00\x00\" // packet length
4890 * "\x01" // packet number
4891 * "\x00\x00\x00\x00" // client capabilities
4892 * "\x00\x00\x00\x01" // max packet
4893 * "\x21" // character set (UTF-8)
4894 * char[23] // All zeroes
4895 * "haproxy\x00" // username (null terminated string)
4896 * "\x00" // filler (always 0x00)
4897 * "\x01\x00\x00" // packet length
4898 * "\x00" // packet number
4899 * "\x01" // COM_QUIT command
4900 * };
4901 */
4902
4903
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004904 if (*(args[2])) {
4905 int cur_arg = 2;
4906
4907 while (*(args[cur_arg])) {
4908 if (strcmp(args[cur_arg], "user") == 0) {
4909 char *mysqluser;
4910 int packetlen, reqlen, userlen;
4911
4912 /* suboption header - needs additional argument for it */
4913 if (*(args[cur_arg+1]) == 0) {
4914 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4915 file, linenum, args[0], args[1], args[cur_arg]);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919 mysqluser = args[cur_arg + 1];
4920 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004921
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004922 if (*(args[cur_arg+2])) {
4923 if (!strcmp(args[cur_arg+2], "post-41")) {
4924 packetlen = userlen + 7 + 27;
4925 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004926
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004927 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004928 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004929 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004930
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004931 snprintf(curproxy->check_req, 4, "%c%c%c",
4932 ((unsigned char) packetlen & 0xff),
4933 ((unsigned char) (packetlen >> 8) & 0xff),
4934 ((unsigned char) (packetlen >> 16) & 0xff));
4935
4936 curproxy->check_req[3] = 1;
4937 curproxy->check_req[5] = 130;
4938 curproxy->check_req[11] = 1;
4939 curproxy->check_req[12] = 33;
4940 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4941 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4942 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4943 cur_arg += 3;
4944 } else {
4945 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
4949 } else {
4950 packetlen = userlen + 7;
4951 reqlen = packetlen + 9;
4952
4953 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004954 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004955 curproxy->check_len = reqlen;
4956
4957 snprintf(curproxy->check_req, 4, "%c%c%c",
4958 ((unsigned char) packetlen & 0xff),
4959 ((unsigned char) (packetlen >> 8) & 0xff),
4960 ((unsigned char) (packetlen >> 16) & 0xff));
4961
4962 curproxy->check_req[3] = 1;
4963 curproxy->check_req[5] = 128;
4964 curproxy->check_req[8] = 1;
4965 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4966 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4967 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4968 cur_arg += 2;
4969 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004970 } else {
4971 /* unknown suboption - catchall */
4972 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4973 file, linenum, args[0], args[1]);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
4977 } /* end while loop */
4978 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004979 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004980 else if (!strcmp(args[1], "ldap-check")) {
4981 /* use LDAP request to check servers' health */
4982 free(curproxy->check_req);
4983 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004984 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004985 curproxy->options2 |= PR_O2_LDAP_CHK;
4986
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004987 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004988 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4989 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004990 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4991 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004992 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004993 else if (!strcmp(args[1], "spop-check")) {
4994 if (curproxy == &defproxy) {
4995 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4996 file, linenum, args[0], args[1]);
4997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999 }
5000 if (curproxy->cap & PR_CAP_FE) {
5001 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5002 file, linenum, args[0], args[1]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
5006
5007 /* use SPOE request to check servers' health */
5008 free(curproxy->check_req);
5009 curproxy->check_req = NULL;
5010 curproxy->options2 &= ~PR_O2_CHK_ANY;
5011 curproxy->options2 |= PR_O2_SPOP_CHK;
5012
Christopher Faulet8ef75252017-02-20 22:56:03 +01005013 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005014 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5019 goto out;
5020 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005021 else if (!strcmp(args[1], "tcp-check")) {
5022 /* use raw TCPCHK send/expect to check servers' health */
5023 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5024 err_code |= ERR_WARN;
5025
5026 free(curproxy->check_req);
5027 curproxy->check_req = NULL;
5028 curproxy->options2 &= ~PR_O2_CHK_ANY;
5029 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005030 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5031 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005032 }
Simon Horman98637e52014-06-20 12:30:16 +09005033 else if (!strcmp(args[1], "external-check")) {
5034 /* excute an external command to check servers' health */
5035 free(curproxy->check_req);
5036 curproxy->check_req = NULL;
5037 curproxy->options2 &= ~PR_O2_CHK_ANY;
5038 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005039 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5040 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005041 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005042 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005043 int cur_arg;
5044
5045 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5046 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005047 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005048
Willy Tarreau87cf5142011-08-19 22:57:24 +02005049 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005050
5051 free(curproxy->fwdfor_hdr_name);
5052 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5053 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5054
5055 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5056 cur_arg = 2;
5057 while (*(args[cur_arg])) {
5058 if (!strcmp(args[cur_arg], "except")) {
5059 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005060 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005061 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5062 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005065 }
5066 /* flush useless bits */
5067 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005068 cur_arg += 2;
5069 } else if (!strcmp(args[cur_arg], "header")) {
5070 /* suboption header - needs additional argument for it */
5071 if (*(args[cur_arg+1]) == 0) {
5072 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5073 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005076 }
5077 free(curproxy->fwdfor_hdr_name);
5078 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5079 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5080 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005081 } else if (!strcmp(args[cur_arg], "if-none")) {
5082 curproxy->options &= ~PR_O_FF_ALWAYS;
5083 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005084 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005085 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005086 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005087 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005090 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005091 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005092 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005093 else if (!strcmp(args[1], "originalto")) {
5094 int cur_arg;
5095
5096 /* insert x-original-to field, but not for the IP address listed as an except.
5097 * set default options (ie: bitfield, header name, etc)
5098 */
5099
5100 curproxy->options |= PR_O_ORGTO;
5101
5102 free(curproxy->orgto_hdr_name);
5103 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5104 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5105
Willy Tarreau87cf5142011-08-19 22:57:24 +02005106 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005107 cur_arg = 2;
5108 while (*(args[cur_arg])) {
5109 if (!strcmp(args[cur_arg], "except")) {
5110 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005111 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 +02005112 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5113 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005116 }
5117 /* flush useless bits */
5118 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5119 cur_arg += 2;
5120 } else if (!strcmp(args[cur_arg], "header")) {
5121 /* suboption header - needs additional argument for it */
5122 if (*(args[cur_arg+1]) == 0) {
5123 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5124 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005127 }
5128 free(curproxy->orgto_hdr_name);
5129 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5130 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5131 cur_arg += 2;
5132 } else {
5133 /* unknown suboption - catchall */
5134 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5135 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005138 }
5139 } /* end while loop */
5140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 else {
5142 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005148 else if (!strcmp(args[0], "default_backend")) {
5149 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005151
5152 if (*(args[1]) == 0) {
5153 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005156 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005157 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005158 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005159
5160 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5161 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005166
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005167 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5168 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 +01005169 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 /* enable reconnections to dispatch */
5172 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005173
5174 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005177 else if (!strcmp(args[0], "http-reuse")) {
5178 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5179 err_code |= ERR_WARN;
5180
5181 if (strcmp(args[1], "never") == 0) {
5182 /* enable a graceful server shutdown on an HTTP 404 response */
5183 curproxy->options &= ~PR_O_REUSE_MASK;
5184 curproxy->options |= PR_O_REUSE_NEVR;
5185 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5186 goto out;
5187 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005188 else if (strcmp(args[1], "safe") == 0) {
5189 /* enable a graceful server shutdown on an HTTP 404 response */
5190 curproxy->options &= ~PR_O_REUSE_MASK;
5191 curproxy->options |= PR_O_REUSE_SAFE;
5192 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5193 goto out;
5194 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005195 else if (strcmp(args[1], "aggressive") == 0) {
5196 curproxy->options &= ~PR_O_REUSE_MASK;
5197 curproxy->options |= PR_O_REUSE_AGGR;
5198 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5199 goto out;
5200 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005201 else if (strcmp(args[1], "always") == 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_ALWS;
5205 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5206 goto out;
5207 }
5208 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005209 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005214 else if (!strcmp(args[0], "http-check")) {
5215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005217
5218 if (strcmp(args[1], "disable-on-404") == 0) {
5219 /* enable a graceful server shutdown on an HTTP 404 response */
5220 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005221 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5222 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005223 }
Willy Tarreauef781042010-01-27 11:53:01 +01005224 else if (strcmp(args[1], "send-state") == 0) {
5225 /* enable emission of the apparent state of a server in HTTP checks */
5226 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005227 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5228 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005229 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005230 else if (strcmp(args[1], "expect") == 0) {
5231 const char *ptr_arg;
5232 int cur_arg;
5233
5234 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5235 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
5238 }
5239
5240 cur_arg = 2;
5241 /* consider exclamation marks, sole or at the beginning of a word */
5242 while (*(ptr_arg = args[cur_arg])) {
5243 while (*ptr_arg == '!') {
5244 curproxy->options2 ^= PR_O2_EXP_INV;
5245 ptr_arg++;
5246 }
5247 if (*ptr_arg)
5248 break;
5249 cur_arg++;
5250 }
5251 /* now ptr_arg points to the beginning of a word past any possible
5252 * exclamation mark, and cur_arg is the argument which holds this word.
5253 */
5254 if (strcmp(ptr_arg, "status") == 0) {
5255 if (!*(args[cur_arg + 1])) {
5256 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5257 file, linenum, args[0], args[1], ptr_arg);
5258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260 }
5261 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005262 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005263 curproxy->expect_str = strdup(args[cur_arg + 1]);
5264 }
5265 else if (strcmp(ptr_arg, "string") == 0) {
5266 if (!*(args[cur_arg + 1])) {
5267 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5268 file, linenum, args[0], args[1], ptr_arg);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005273 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005274 curproxy->expect_str = strdup(args[cur_arg + 1]);
5275 }
5276 else if (strcmp(ptr_arg, "rstatus") == 0) {
5277 if (!*(args[cur_arg + 1])) {
5278 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5279 file, linenum, args[0], args[1], ptr_arg);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005284 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005285 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005286 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005287 free(curproxy->expect_regex);
5288 curproxy->expect_regex = NULL;
5289 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005290 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005291 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5292 error = NULL;
5293 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5294 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5295 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5296 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300 }
5301 else if (strcmp(ptr_arg, "rstring") == 0) {
5302 if (!*(args[cur_arg + 1])) {
5303 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5304 file, linenum, args[0], args[1], ptr_arg);
5305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005309 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005310 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005311 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005312 free(curproxy->expect_regex);
5313 curproxy->expect_regex = NULL;
5314 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005315 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005316 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5317 error = NULL;
5318 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5319 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5320 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5321 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325 }
5326 else {
5327 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5328 file, linenum, args[0], args[1], ptr_arg);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005333 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005334 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 +02005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005337 }
5338 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005339 else if (!strcmp(args[0], "tcp-check")) {
5340 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5341 err_code |= ERR_WARN;
5342
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005343 if (strcmp(args[1], "comment") == 0) {
5344 int cur_arg;
5345 struct tcpcheck_rule *tcpcheck;
5346
5347 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005348 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005349 tcpcheck->action = TCPCHK_ACT_COMMENT;
5350
5351 if (!*args[cur_arg + 1]) {
5352 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5353 file, linenum, args[cur_arg]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357
5358 tcpcheck->comment = strdup(args[cur_arg + 1]);
5359
5360 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005361 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5362 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005363 }
5364 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005365 const char *ptr_arg;
5366 int cur_arg;
5367 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005368
5369 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005370 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5371 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5372 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5373 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5374 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005375
Willy Tarreau5581c272015-05-13 12:24:53 +02005376 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5377 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5378 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5379 file, linenum);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005382 }
5383
5384 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005385 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005386 tcpcheck->action = TCPCHK_ACT_CONNECT;
5387
5388 /* parsing each parameters to fill up the rule */
5389 while (*(ptr_arg = args[cur_arg])) {
5390 /* tcp port */
5391 if (strcmp(args[cur_arg], "port") == 0) {
5392 if ( (atol(args[cur_arg + 1]) > 65535) ||
5393 (atol(args[cur_arg + 1]) < 1) ){
5394 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5395 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399 tcpcheck->port = atol(args[cur_arg + 1]);
5400 cur_arg += 2;
5401 }
5402 /* send proxy protocol */
5403 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5404 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5405 cur_arg++;
5406 }
5407#ifdef USE_OPENSSL
5408 else if (strcmp(args[cur_arg], "ssl") == 0) {
5409 curproxy->options |= PR_O_TCPCHK_SSL;
5410 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5411 cur_arg++;
5412 }
5413#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005414 /* comment for this tcpcheck line */
5415 else if (strcmp(args[cur_arg], "comment") == 0) {
5416 if (!*args[cur_arg + 1]) {
5417 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5418 file, linenum, args[cur_arg]);
5419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
5422 tcpcheck->comment = strdup(args[cur_arg + 1]);
5423 cur_arg += 2;
5424 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005425 else {
5426#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005427 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 +01005428#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005429 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 +01005430#endif /* USE_OPENSSL */
5431 file, linenum, args[0], args[1], args[cur_arg]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435
5436 }
5437
5438 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5439 }
5440 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005441 if (! *(args[2]) ) {
5442 /* SEND string expected */
5443 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5444 file, linenum, args[0], args[1], args[2]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 } else {
5448 struct tcpcheck_rule *tcpcheck;
5449
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005450 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005451
5452 tcpcheck->action = TCPCHK_ACT_SEND;
5453 tcpcheck->string_len = strlen(args[2]);
5454 tcpcheck->string = strdup(args[2]);
5455 tcpcheck->expect_regex = NULL;
5456
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005457 /* comment for this tcpcheck line */
5458 if (strcmp(args[3], "comment") == 0) {
5459 if (!*args[4]) {
5460 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5461 file, linenum, args[3]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465 tcpcheck->comment = strdup(args[4]);
5466 }
5467
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5469 }
5470 }
5471 else if (strcmp(args[1], "send-binary") == 0) {
5472 if (! *(args[2]) ) {
5473 /* SEND binary string expected */
5474 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5475 file, linenum, args[0], args[1], args[2]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 } else {
5479 struct tcpcheck_rule *tcpcheck;
5480 char *err = NULL;
5481
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005482 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005483
5484 tcpcheck->action = TCPCHK_ACT_SEND;
5485 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5486 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5487 file, linenum, args[0], args[1], args[2], err);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
5491 tcpcheck->expect_regex = NULL;
5492
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005493 /* comment for this tcpcheck line */
5494 if (strcmp(args[3], "comment") == 0) {
5495 if (!*args[4]) {
5496 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5497 file, linenum, args[3]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
5501 tcpcheck->comment = strdup(args[4]);
5502 }
5503
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005504 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5505 }
5506 }
5507 else if (strcmp(args[1], "expect") == 0) {
5508 const char *ptr_arg;
5509 int cur_arg;
5510 int inverse = 0;
5511
5512 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5513 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517
5518 cur_arg = 2;
5519 /* consider exclamation marks, sole or at the beginning of a word */
5520 while (*(ptr_arg = args[cur_arg])) {
5521 while (*ptr_arg == '!') {
5522 inverse = !inverse;
5523 ptr_arg++;
5524 }
5525 if (*ptr_arg)
5526 break;
5527 cur_arg++;
5528 }
5529 /* now ptr_arg points to the beginning of a word past any possible
5530 * exclamation mark, and cur_arg is the argument which holds this word.
5531 */
5532 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005533 struct tcpcheck_rule *tcpcheck;
5534 char *err = NULL;
5535
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536 if (!*(args[cur_arg + 1])) {
5537 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5538 file, linenum, args[0], args[1], ptr_arg);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005542
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005543 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005544
5545 tcpcheck->action = TCPCHK_ACT_EXPECT;
5546 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5547 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5548 file, linenum, args[0], args[1], args[2], err);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
5552 tcpcheck->expect_regex = NULL;
5553 tcpcheck->inverse = inverse;
5554
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005555 /* tcpcheck comment */
5556 cur_arg += 2;
5557 if (strcmp(args[cur_arg], "comment") == 0) {
5558 if (!*args[cur_arg + 1]) {
5559 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5560 file, linenum, args[cur_arg + 1]);
5561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
5563 }
5564 tcpcheck->comment = strdup(args[cur_arg + 1]);
5565 }
5566
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005567 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5568 }
5569 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005570 struct tcpcheck_rule *tcpcheck;
5571
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005572 if (!*(args[cur_arg + 1])) {
5573 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5574 file, linenum, args[0], args[1], ptr_arg);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005579 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580
5581 tcpcheck->action = TCPCHK_ACT_EXPECT;
5582 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5583 tcpcheck->string = strdup(args[cur_arg + 1]);
5584 tcpcheck->expect_regex = NULL;
5585 tcpcheck->inverse = inverse;
5586
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005587 /* tcpcheck comment */
5588 cur_arg += 2;
5589 if (strcmp(args[cur_arg], "comment") == 0) {
5590 if (!*args[cur_arg + 1]) {
5591 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5592 file, linenum, args[cur_arg + 1]);
5593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 tcpcheck->comment = strdup(args[cur_arg + 1]);
5597 }
5598
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005599 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5600 }
5601 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005602 struct tcpcheck_rule *tcpcheck;
5603
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005604 if (!*(args[cur_arg + 1])) {
5605 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5606 file, linenum, args[0], args[1], ptr_arg);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005611 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612
5613 tcpcheck->action = TCPCHK_ACT_EXPECT;
5614 tcpcheck->string_len = 0;
5615 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005616 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5617 error = NULL;
5618 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5619 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5620 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5621 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622 err_code |= ERR_ALERT | ERR_FATAL;
5623 goto out;
5624 }
5625 tcpcheck->inverse = inverse;
5626
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005627 /* tcpcheck comment */
5628 cur_arg += 2;
5629 if (strcmp(args[cur_arg], "comment") == 0) {
5630 if (!*args[cur_arg + 1]) {
5631 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5632 file, linenum, args[cur_arg + 1]);
5633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
5636 tcpcheck->comment = strdup(args[cur_arg + 1]);
5637 }
5638
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005639 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5640 }
5641 else {
5642 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5643 file, linenum, args[0], args[1], ptr_arg);
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
5647 }
5648 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005649 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
5652 }
5653 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005654 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005655 if (curproxy == &defproxy) {
5656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005659 }
5660
Willy Tarreaub80c2302007-11-30 20:51:32 +01005661 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005662 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005663
5664 if (strcmp(args[1], "fail") == 0) {
5665 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005666 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005667 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5668 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005671 }
5672
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005673 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5674 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5675 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005678 }
5679 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5680 }
5681 else {
5682 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005685 }
5686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687#ifdef TPROXY
5688 else if (!strcmp(args[0], "transparent")) {
5689 /* enable transparent proxy connections */
5690 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005691 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
5694#endif
5695 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005696 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005697 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005698
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 if (*(args[1]) == 0) {
5700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
5704 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005705 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005708 else if (!strcmp(args[0], "backlog")) { /* backlog */
5709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005711
5712 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 Tarreauc73ce2b2008-01-06 10:55:10 +01005716 }
5717 curproxy->backlog = 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 Tarreauc73ce2b2008-01-06 10:55:10 +01005720 }
Willy Tarreau86034312006-12-29 00:10:33 +01005721 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005722 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005723 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005724
Willy Tarreau86034312006-12-29 00:10:33 +01005725 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 Tarreau86034312006-12-29 00:10:33 +01005729 }
5730 curproxy->fullconn = 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 Tarreau86034312006-12-29 00:10:33 +01005733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5735 if (*(args[1]) == 0) {
5736 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005740 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5741 if (err) {
5742 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5743 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005746 }
5747 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
5751 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005752 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005753 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005754 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005755
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 if (curproxy == &defproxy) {
5757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005761 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005763
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005764 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005765 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005766 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005768 goto out;
5769 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005770
5771 proto = protocol_by_family(sk->ss_family);
5772 if (!proto || !proto->connect) {
5773 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5774 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
5777 }
5778
5779 if (port1 != port2) {
5780 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5781 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005785
5786 if (!port1) {
5787 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5788 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005792
William Lallemanddf1425a2015-04-28 20:17:49 +02005793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5794 goto out;
5795
Willy Tarreaud5191e72010-02-09 20:50:45 +01005796 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005797 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
5799 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005800 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005802
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005803 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5804 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005805 err_code |= ERR_ALERT | ERR_FATAL;
5806 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005809 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005810 /**
5811 * The syntax for hash-type config element is
5812 * hash-type {map-based|consistent} [[<algo>] avalanche]
5813 *
5814 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5815 */
5816 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005817
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005818 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5819 err_code |= ERR_WARN;
5820
5821 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005822 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5823 }
5824 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005825 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5826 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005827 else if (strcmp(args[1], "avalanche") == 0) {
5828 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]);
5829 err_code |= ERR_ALERT | ERR_FATAL;
5830 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005831 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005832 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005833 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
5836 }
Bhaskar98634f02013-10-29 23:30:51 -04005837
5838 /* set the hash function to use */
5839 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005840 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005841 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005842
5843 /* if consistent with no argument, then avalanche modifier is also applied */
5844 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5845 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005846 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005847 /* set the hash function */
5848 if (!strcmp(args[2], "sdbm")) {
5849 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5850 }
5851 else if (!strcmp(args[2], "djb2")) {
5852 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005853 }
5854 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005855 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005856 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005857 else if (!strcmp(args[2], "crc32")) {
5858 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5859 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005860 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005861 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 -05005862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
5865
5866 /* set the hash modifier */
5867 if (!strcmp(args[3], "avalanche")) {
5868 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5869 }
5870 else if (*args[3]) {
5871 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
5874 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005875 }
William Lallemanda73203e2012-03-12 12:48:57 +01005876 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005877 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5878 if (*(args[1]) == 0) {
5879 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5880 err_code |= ERR_ALERT | ERR_FATAL;
5881 goto out;
5882 }
5883 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5884 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5885 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
5888 }
5889 }
William Lallemanda73203e2012-03-12 12:48:57 +01005890 else if (strcmp(args[0], "unique-id-format") == 0) {
5891 if (!*(args[1])) {
5892 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
William Lallemand3203ff42012-11-11 17:30:56 +01005896 if (*(args[2])) {
5897 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005901 free(curproxy->conf.uniqueid_format_string);
5902 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005903
Willy Tarreau62a61232013-04-12 18:13:46 +02005904 free(curproxy->conf.uif_file);
5905 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5906 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005907 }
William Lallemanda73203e2012-03-12 12:48:57 +01005908
5909 else if (strcmp(args[0], "unique-id-header") == 0) {
5910 if (!*(args[1])) {
5911 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
5914 }
5915 free(curproxy->header_unique_id);
5916 curproxy->header_unique_id = strdup(args[1]);
5917 }
5918
William Lallemand723b73a2012-02-08 16:37:49 +01005919 else if (strcmp(args[0], "log-format") == 0) {
5920 if (!*(args[1])) {
5921 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
5924 }
William Lallemand3203ff42012-11-11 17:30:56 +01005925 if (*(args[2])) {
5926 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
5929 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005930 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5931 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005932
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005933 if (curproxy->conf.logformat_string == default_http_log_format)
5934 oldlogformat = "option httplog";
5935 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5936 oldlogformat = "option tcplog";
5937 else if (curproxy->conf.logformat_string == clf_http_log_format)
5938 oldlogformat = "option httplog clf";
5939 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5940 file, linenum, oldlogformat);
5941 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005942 if (curproxy->conf.logformat_string != default_http_log_format &&
5943 curproxy->conf.logformat_string != default_tcp_log_format &&
5944 curproxy->conf.logformat_string != clf_http_log_format)
5945 free(curproxy->conf.logformat_string);
5946 curproxy->conf.logformat_string = strdup(args[1]);
5947
5948 free(curproxy->conf.lfs_file);
5949 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5950 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005951
5952 /* get a chance to improve log-format error reporting by
5953 * reporting the correct line-number when possible.
5954 */
5955 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5956 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5957 file, linenum, curproxy->id);
5958 err_code |= ERR_WARN;
5959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005961 else if (!strcmp(args[0], "log-format-sd")) {
5962 if (!*(args[1])) {
5963 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
5967 if (*(args[2])) {
5968 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
5973 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5974 free(curproxy->conf.logformat_sd_string);
5975 curproxy->conf.logformat_sd_string = strdup(args[1]);
5976
5977 free(curproxy->conf.lfsd_file);
5978 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5979 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5980
5981 /* get a chance to improve log-format-sd error reporting by
5982 * reporting the correct line-number when possible.
5983 */
5984 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5985 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5986 file, linenum, curproxy->id);
5987 err_code |= ERR_WARN;
5988 }
5989 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005990 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5991 if (*(args[1]) == 0) {
5992 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005996 chunk_destroy(&curproxy->log_tag);
5997 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005998 }
William Lallemand0f99e342011-10-12 17:50:54 +02005999 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6000 /* delete previous herited or defined syslog servers */
6001 struct logsrv *back;
6002
6003 if (*(args[1]) != 0) {
6004 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
6008
William Lallemand723b73a2012-02-08 16:37:49 +01006009 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6010 LIST_DEL(&tmplogsrv->list);
6011 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006012 }
6013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006014 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006015 struct logsrv *logsrv;
6016
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006018 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006019 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006020 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006021 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006022 LIST_INIT(&node->list);
6023 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 }
6026 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006027 struct sockaddr_storage *sk;
6028 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006029 int arg = 0;
6030 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006031
Vincent Bernat02779b62016-04-03 13:48:43 +02006032 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033
Willy Tarreau18324f52014-06-27 18:10:07 +02006034 /* just after the address, a length may be specified */
6035 if (strcmp(args[arg+2], "len") == 0) {
6036 len = atoi(args[arg+3]);
6037 if (len < 80 || len > 65535) {
6038 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6039 file, linenum, args[arg+3]);
6040 err_code |= ERR_ALERT | ERR_FATAL;
6041 goto out;
6042 }
6043 logsrv->maxlen = len;
6044
6045 /* skip these two args */
6046 arg += 2;
6047 }
6048 else
6049 logsrv->maxlen = MAX_SYSLOG_LEN;
6050
Christopher Faulet084aa962017-08-29 16:54:41 +02006051 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006052 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006053
Dragan Dosen1322d092015-09-22 16:05:32 +02006054 /* after the length, a format may be specified */
6055 if (strcmp(args[arg+2], "format") == 0) {
6056 logsrv->format = get_log_format(args[arg+3]);
6057 if (logsrv->format < 0) {
6058 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6059 err_code |= ERR_ALERT | ERR_FATAL;
6060 goto out;
6061 }
6062
6063 /* skip these two args */
6064 arg += 2;
6065 }
6066
William Lallemanddf1425a2015-04-28 20:17:49 +02006067 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6068 goto out;
6069
Willy Tarreau18324f52014-06-27 18:10:07 +02006070 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006071 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006072 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006073 err_code |= ERR_ALERT | ERR_FATAL;
6074 goto out;
6075
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076 }
6077
William Lallemand0f99e342011-10-12 17:50:54 +02006078 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006079 if (*(args[arg+3])) {
6080 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006081 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006082 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006083 err_code |= ERR_ALERT | ERR_FATAL;
6084 goto out;
6085
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086 }
6087 }
6088
William Lallemand0f99e342011-10-12 17:50:54 +02006089 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006090 if (*(args[arg+4])) {
6091 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006092 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006093 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
6096
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006097 }
6098 }
6099
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006100 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006101 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006102 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006103 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006104 goto out;
6105 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006106
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006107 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006108
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006109 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006110 if (port1 != port2) {
6111 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6112 file, linenum, args[0], args[1]);
6113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
6115 }
6116
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006117 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006118 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 }
William Lallemand0f99e342011-10-12 17:50:54 +02006120
6121 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006122 }
6123 else {
6124 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6125 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006126 err_code |= ERR_ALERT | ERR_FATAL;
6127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 }
6129 }
6130 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006131 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006132 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006133 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006134 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006135
Willy Tarreau977b8e42006-12-29 14:19:17 +01006136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006137 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006138
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006140 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6141 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006145
6146 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006147 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6148 free(curproxy->conn_src.iface_name);
6149 curproxy->conn_src.iface_name = NULL;
6150 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006151
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006152 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006153 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006154 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006155 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006156 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006157 goto out;
6158 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006159
6160 proto = protocol_by_family(sk->ss_family);
6161 if (!proto || !proto->connect) {
6162 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006163 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006164 err_code |= ERR_ALERT | ERR_FATAL;
6165 goto out;
6166 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006167
6168 if (port1 != port2) {
6169 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6170 file, linenum, args[0], args[1]);
6171 err_code |= ERR_ALERT | ERR_FATAL;
6172 goto out;
6173 }
6174
Willy Tarreauef9a3602012-12-08 22:29:20 +01006175 curproxy->conn_src.source_addr = *sk;
6176 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177
6178 cur_arg = 2;
6179 while (*(args[cur_arg])) {
6180 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006181#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006182 if (!*args[cur_arg + 1]) {
6183 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6184 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006185 err_code |= ERR_ALERT | ERR_FATAL;
6186 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006187 }
6188
6189 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006190 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6191 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006192 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006193 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6194 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006195 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6196 char *name, *end;
6197
6198 name = args[cur_arg+1] + 7;
6199 while (isspace(*name))
6200 name++;
6201
6202 end = name;
6203 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6204 end++;
6205
Willy Tarreauef9a3602012-12-08 22:29:20 +01006206 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6207 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6208 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6209 curproxy->conn_src.bind_hdr_len = end - name;
6210 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6211 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6212 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006213
6214 /* now look for an occurrence number */
6215 while (isspace(*end))
6216 end++;
6217 if (*end == ',') {
6218 end++;
6219 name = end;
6220 if (*end == '-')
6221 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006222 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006223 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006224 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006225 }
6226
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006228 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6229 " occurrences values smaller than %d.\n",
6230 file, linenum, MAX_HDR_HISTORY);
6231 err_code |= ERR_ALERT | ERR_FATAL;
6232 goto out;
6233 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006234 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006235 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006236
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006237 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006238 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006239 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006240 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006241 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006242 goto out;
6243 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006244
6245 proto = protocol_by_family(sk->ss_family);
6246 if (!proto || !proto->connect) {
6247 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6248 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
6251 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006252
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006253 if (port1 != port2) {
6254 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6255 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006256 err_code |= ERR_ALERT | ERR_FATAL;
6257 goto out;
6258 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006259 curproxy->conn_src.tproxy_addr = *sk;
6260 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006261 }
6262 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006263#else /* no TPROXY support */
6264 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006265 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006266 err_code |= ERR_ALERT | ERR_FATAL;
6267 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006268#endif
6269 cur_arg += 2;
6270 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006271 }
6272
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6274#ifdef SO_BINDTODEVICE
6275 if (!*args[cur_arg + 1]) {
6276 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006280 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006281 free(curproxy->conn_src.iface_name);
6282 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6283 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006284 global.last_checks |= LSTCHK_NETADM;
6285#else
6286 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6287 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006290#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006291 cur_arg += 2;
6292 continue;
6293 }
6294 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006295 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006296 err_code |= ERR_ALERT | ERR_FATAL;
6297 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006299 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006300 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6301 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6302 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= ERR_ALERT | ERR_FATAL;
6304 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006307 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006310 err_code |= ERR_ALERT | ERR_FATAL;
6311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006312 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006313
6314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006315 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006316 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 }
6320 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006321 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006322 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006323 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006324 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 }
6327 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006329 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006330 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 }
6334 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006336 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006337 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 }
6341 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006343 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006348 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006350 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006351 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006353 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006359 err_code |= ERR_ALERT | ERR_FATAL;
6360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006361 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362
6363 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006364 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006365 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 }
6369 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006371 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006372 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 }
6376 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006378 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006379 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382 }
6383 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006385 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006386 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006387 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006389 }
6390 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006392 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006393 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006394 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006397 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006398 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006399 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006400 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006402 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006405 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006406
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 if (curproxy == &defproxy) {
6408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006409 err_code |= ERR_ALERT | ERR_FATAL;
6410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006412 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006413 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 if (*(args[1]) == 0) {
6416 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006417 err_code |= ERR_ALERT | ERR_FATAL;
6418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006420
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006421 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006422 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6423 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6424 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006425 err_code |= ERR_ALERT | ERR_FATAL;
6426 goto out;
6427 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006428 err_code |= warnif_cond_conflicts(cond,
6429 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6430 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006431 }
6432 else if (*args[2]) {
6433 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6434 file, linenum, args[0], args[2]);
6435 err_code |= ERR_ALERT | ERR_FATAL;
6436 goto out;
6437 }
6438
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006439 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006440 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006441 wl->s = strdup(args[1]);
6442 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006443 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
6445 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006452
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006454 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006455 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 }
6459 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006461 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006462 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006463 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006465 }
6466 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006468 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006469 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006470 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 }
6473 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6476 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006477 err_code |= ERR_ALERT | ERR_FATAL;
6478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479 }
6480
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006482 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006483 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 }
6487 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006488 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006489 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006490 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006491 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006493 }
6494 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006496 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006497 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006498 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006500 }
6501 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006502 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006503
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 if (curproxy == &defproxy) {
6505 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006509 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006510 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 if (*(args[1]) == 0) {
6513 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006514 err_code |= ERR_ALERT | ERR_FATAL;
6515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
6517
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006518 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006519 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6520 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6521 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006522 err_code |= ERR_ALERT | ERR_FATAL;
6523 goto out;
6524 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006525 err_code |= warnif_cond_conflicts(cond,
6526 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6527 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006528 }
6529 else if (*args[2]) {
6530 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6531 file, linenum, args[0], args[2]);
6532 err_code |= ERR_ALERT | ERR_FATAL;
6533 goto out;
6534 }
6535
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006536 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006537 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006538 wl->s = strdup(args[1]);
6539 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 }
6541 else if (!strcmp(args[0], "errorloc") ||
6542 !strcmp(args[0], "errorloc302") ||
6543 !strcmp(args[0], "errorloc303")) { /* error location */
6544 int errnum, errlen;
6545 char *err;
6546
Willy Tarreau977b8e42006-12-29 14:19:17 +01006547 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006548 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006549
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006551 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006552 err_code |= ERR_ALERT | ERR_FATAL;
6553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006554 }
6555
6556 errnum = atol(args[1]);
6557 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006558 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6559 err = malloc(errlen);
6560 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006562 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6563 err = malloc(errlen);
6564 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 }
6566
Willy Tarreau0f772532006-12-23 20:51:41 +01006567 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6568 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006569 chunk_destroy(&curproxy->errmsg[rc]);
6570 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006571 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006574
6575 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006576 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6577 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 free(err);
6579 }
6580 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006581 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6582 int errnum, errlen, fd;
6583 char *err;
6584 struct stat stat;
6585
6586 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006587 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006588
6589 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006590 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
6592 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006593 }
6594
6595 fd = open(args[2], O_RDONLY);
6596 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6597 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6598 file, linenum, args[2], args[1]);
6599 if (fd >= 0)
6600 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006601 err_code |= ERR_ALERT | ERR_FATAL;
6602 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006603 }
6604
Willy Tarreau27a674e2009-08-17 07:23:33 +02006605 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006606 errlen = stat.st_size;
6607 } else {
6608 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006609 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006610 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006611 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006612 }
6613
6614 err = malloc(errlen); /* malloc() must succeed during parsing */
6615 errnum = read(fd, err, errlen);
6616 if (errnum != errlen) {
6617 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6618 file, linenum, args[2], args[1]);
6619 close(fd);
6620 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_ALERT | ERR_FATAL;
6622 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006623 }
6624 close(fd);
6625
6626 errnum = atol(args[1]);
6627 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6628 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006629 chunk_destroy(&curproxy->errmsg[rc]);
6630 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006631 break;
6632 }
6633 }
6634
6635 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006636 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6637 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006639 free(err);
6640 }
6641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006642 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006643 struct cfg_kw_list *kwl;
6644 int index;
6645
6646 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6647 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6648 if (kwl->kw[index].section != CFG_LISTEN)
6649 continue;
6650 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6651 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006652 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006653 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006654 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006657 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006658 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006659 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006660 err_code |= ERR_WARN;
6661 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006662 }
Willy Tarreau93893792009-07-23 13:19:11 +02006663 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006664 }
6665 }
6666 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006667
Willy Tarreau6daf3432008-01-22 16:44:08 +01006668 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006669 err_code |= ERR_ALERT | ERR_FATAL;
6670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671 }
Willy Tarreau93893792009-07-23 13:19:11 +02006672 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006673 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006674 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006675}
6676
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006678cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6679{
6680#ifdef CONFIG_HAP_NS
6681 const char *err;
6682 const char *item = args[0];
6683
6684 if (!strcmp(item, "namespace_list")) {
6685 return 0;
6686 }
6687 else if (!strcmp(item, "namespace")) {
6688 size_t idx = 1;
6689 const char *current;
6690 while (*(current = args[idx++])) {
6691 err = invalid_char(current);
6692 if (err) {
6693 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6694 file, linenum, *err, item, current);
6695 return ERR_ALERT | ERR_FATAL;
6696 }
6697
6698 if (netns_store_lookup(current, strlen(current))) {
6699 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6700 file, linenum, current);
6701 return ERR_ALERT | ERR_FATAL;
6702 }
6703 if (!netns_store_insert(current)) {
6704 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6705 file, linenum, current);
6706 return ERR_ALERT | ERR_FATAL;
6707 }
6708 }
6709 }
6710
6711 return 0;
6712#else
6713 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6714 file, linenum);
6715 return ERR_ALERT | ERR_FATAL;
6716#endif
6717}
6718
6719int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6721{
6722
6723 int err_code = 0;
6724 const char *err;
6725
6726 if (!strcmp(args[0], "userlist")) { /* new userlist */
6727 struct userlist *newul;
6728
6729 if (!*args[1]) {
6730 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6731 file, linenum, args[0]);
6732 err_code |= ERR_ALERT | ERR_FATAL;
6733 goto out;
6734 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6736 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737
6738 err = invalid_char(args[1]);
6739 if (err) {
6740 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6741 file, linenum, *err, args[0], args[1]);
6742 err_code |= ERR_ALERT | ERR_FATAL;
6743 goto out;
6744 }
6745
6746 for (newul = userlist; newul; newul = newul->next)
6747 if (!strcmp(newul->name, args[1])) {
6748 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6749 file, linenum, args[1]);
6750 err_code |= ERR_WARN;
6751 goto out;
6752 }
6753
Vincent Bernat02779b62016-04-03 13:48:43 +02006754 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006755 if (!newul) {
6756 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6757 err_code |= ERR_ALERT | ERR_ABORT;
6758 goto out;
6759 }
6760
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006761 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006762 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006763 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6764 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006765 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 goto out;
6767 }
6768
6769 newul->next = userlist;
6770 userlist = newul;
6771
6772 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006773 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006774 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006775 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776
6777 if (!*args[1]) {
6778 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6779 file, linenum, args[0]);
6780 err_code |= ERR_ALERT | ERR_FATAL;
6781 goto out;
6782 }
6783
6784 err = invalid_char(args[1]);
6785 if (err) {
6786 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6787 file, linenum, *err, args[0], args[1]);
6788 err_code |= ERR_ALERT | ERR_FATAL;
6789 goto out;
6790 }
6791
William Lallemand4ac9f542015-05-28 18:03:51 +02006792 if (!userlist)
6793 goto out;
6794
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006795 for (ag = userlist->groups; ag; ag = ag->next)
6796 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006797 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6798 file, linenum, args[1], userlist->name);
6799 err_code |= ERR_ALERT;
6800 goto out;
6801 }
6802
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006803 ag = calloc(1, sizeof(*ag));
6804 if (!ag) {
6805 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6806 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006807 goto out;
6808 }
6809
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006811 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6813 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006814 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006815 goto out;
6816 }
6817
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006818 cur_arg = 2;
6819
6820 while (*args[cur_arg]) {
6821 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006822 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006823 cur_arg += 2;
6824 continue;
6825 } else {
6826 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6827 file, linenum, args[0]);
6828 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006829 free(ag->groupusers);
6830 free(ag->name);
6831 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006832 goto out;
6833 }
6834 }
6835
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006836 ag->next = userlist->groups;
6837 userlist->groups = ag;
6838
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006839 } else if (!strcmp(args[0], "user")) { /* new user */
6840 struct auth_users *newuser;
6841 int cur_arg;
6842
6843 if (!*args[1]) {
6844 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6845 file, linenum, args[0]);
6846 err_code |= ERR_ALERT | ERR_FATAL;
6847 goto out;
6848 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006849 if (!userlist)
6850 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006851
6852 for (newuser = userlist->users; newuser; newuser = newuser->next)
6853 if (!strcmp(newuser->user, args[1])) {
6854 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6855 file, linenum, args[1], userlist->name);
6856 err_code |= ERR_ALERT;
6857 goto out;
6858 }
6859
Vincent Bernat02779b62016-04-03 13:48:43 +02006860 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006861 if (!newuser) {
6862 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6863 err_code |= ERR_ALERT | ERR_ABORT;
6864 goto out;
6865 }
6866
6867 newuser->user = strdup(args[1]);
6868
6869 newuser->next = userlist->users;
6870 userlist->users = newuser;
6871
6872 cur_arg = 2;
6873
6874 while (*args[cur_arg]) {
6875 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006876#ifdef CONFIG_HAP_CRYPT
6877 if (!crypt("", args[cur_arg + 1])) {
6878 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6879 file, linenum, newuser->user);
6880 err_code |= ERR_ALERT | ERR_FATAL;
6881 goto out;
6882 }
6883#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006884 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6885 file, linenum);
6886 err_code |= ERR_ALERT;
6887#endif
6888 newuser->pass = strdup(args[cur_arg + 1]);
6889 cur_arg += 2;
6890 continue;
6891 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6892 newuser->pass = strdup(args[cur_arg + 1]);
6893 newuser->flags |= AU_O_INSECURE;
6894 cur_arg += 2;
6895 continue;
6896 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006897 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898 cur_arg += 2;
6899 continue;
6900 } else {
6901 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6902 file, linenum, args[0]);
6903 err_code |= ERR_ALERT | ERR_FATAL;
6904 goto out;
6905 }
6906 }
6907 } else {
6908 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6909 err_code |= ERR_ALERT | ERR_FATAL;
6910 }
6911
6912out:
6913 return err_code;
6914}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915
Christopher Faulet79bdef32016-11-04 22:36:15 +01006916int
6917cfg_parse_scope(const char *file, int linenum, char *line)
6918{
6919 char *beg, *end, *scope = NULL;
6920 int err_code = 0;
6921 const char *err;
6922
6923 beg = line + 1;
6924 end = strchr(beg, ']');
6925
6926 /* Detect end of scope declaration */
6927 if (!end || end == beg) {
6928 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6929 file, linenum);
6930 err_code |= ERR_ALERT | ERR_FATAL;
6931 goto out;
6932 }
6933
6934 /* Get scope name and check its validity */
6935 scope = my_strndup(beg, end-beg);
6936 err = invalid_char(scope);
6937 if (err) {
6938 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6939 file, linenum, *err);
6940 err_code |= ERR_ALERT | ERR_ABORT;
6941 goto out;
6942 }
6943
6944 /* Be sure to have a scope declaration alone on its line */
6945 line = end+1;
6946 while (isspace((unsigned char)*line))
6947 line++;
6948 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6949 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6950 file, linenum, *line);
6951 err_code |= ERR_ALERT | ERR_ABORT;
6952 goto out;
6953 }
6954
6955 /* We have a valid scope declaration, save it */
6956 free(cfg_scope);
6957 cfg_scope = scope;
6958 scope = NULL;
6959
6960 out:
6961 free(scope);
6962 return err_code;
6963}
6964
Willy Tarreaubaaee002006-06-26 02:48:02 +02006965/*
6966 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006967 * Returns the error code, 0 if OK, or any combination of :
6968 * - ERR_ABORT: must abort ASAP
6969 * - ERR_FATAL: we can continue parsing but not start the service
6970 * - ERR_WARN: a warning has been emitted
6971 * - ERR_ALERT: an alert has been emitted
6972 * Only the two first ones can stop processing, the two others are just
6973 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006975int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006976{
William Lallemand64e84512015-05-12 14:25:37 +02006977 char *thisline;
6978 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979 FILE *f;
6980 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006981 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006982 struct cfg_section *cs = NULL;
6983 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006984 int readbytes = 0;
6985
6986 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006987 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006988 return -1;
6989 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006990
David Carlier97880bb2016-04-08 10:35:26 +01006991 if ((f=fopen(file,"r")) == NULL) {
6992 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995
William Lallemandb2f07452015-05-12 14:27:13 +02006996next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006997 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006998 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006999 char *end;
7000 char *args[MAX_LINE_ARGS + 1];
7001 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007002 int dquote = 0; /* double quote */
7003 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007004
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 linenum++;
7006
7007 end = line + strlen(line);
7008
William Lallemand64e84512015-05-12 14:25:37 +02007009 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007010 /* Check if we reached the limit and the last char is not \n.
7011 * Watch out for the last line without the terminating '\n'!
7012 */
William Lallemand64e84512015-05-12 14:25:37 +02007013 char *newline;
7014 int newlinesize = linesize * 2;
7015
7016 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7017 if (newline == NULL) {
7018 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7019 file, linenum);
7020 err_code |= ERR_ALERT | ERR_FATAL;
7021 continue;
7022 }
7023
7024 readbytes = linesize - 1;
7025 linesize = newlinesize;
7026 thisline = newline;
7027 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007028 }
7029
William Lallemand64e84512015-05-12 14:25:37 +02007030 readbytes = 0;
7031
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007033 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007035
Christopher Faulet79bdef32016-11-04 22:36:15 +01007036
7037 if (*line == '[') {/* This is the begining if a scope */
7038 err_code |= cfg_parse_scope(file, linenum, line);
7039 goto next_line;
7040 }
7041
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 arg = 0;
7043 args[arg] = line;
7044
7045 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007046 if (*line == '"' && !squote) { /* double quote outside single quotes */
7047 if (dquote)
7048 dquote = 0;
7049 else
7050 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007051 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007052 end--;
7053 }
7054 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7055 if (squote)
7056 squote = 0;
7057 else
7058 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007059 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007060 end--;
7061 }
7062 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007063 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7064 * C equivalent value. Other combinations left unchanged (eg: \1).
7065 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007066 int skip = 0;
7067 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7068 *line = line[1];
7069 skip = 1;
7070 }
7071 else if (line[1] == 'r') {
7072 *line = '\r';
7073 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007075 else if (line[1] == 'n') {
7076 *line = '\n';
7077 skip = 1;
7078 }
7079 else if (line[1] == 't') {
7080 *line = '\t';
7081 skip = 1;
7082 }
7083 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007084 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 unsigned char hex1, hex2;
7086 hex1 = toupper(line[2]) - '0';
7087 hex2 = toupper(line[3]) - '0';
7088 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7089 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7090 *line = (hex1<<4) + hex2;
7091 skip = 3;
7092 }
7093 else {
7094 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007095 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007097 } else if (line[1] == '"') {
7098 *line = '"';
7099 skip = 1;
7100 } else if (line[1] == '\'') {
7101 *line = '\'';
7102 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007103 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7104 *line = '$';
7105 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 }
7107 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007108 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109 end -= skip;
7110 }
7111 line++;
7112 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007113 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 /* end of string, end of loop */
7115 *line = 0;
7116 break;
7117 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007118 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007119 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007120 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007121 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007122 line++;
7123 args[++arg] = line;
7124 }
William Lallemandb2f07452015-05-12 14:27:13 +02007125 else if (dquote && *line == '$') {
7126 /* environment variables are evaluated inside double quotes */
7127 char *var_beg;
7128 char *var_end;
7129 char save_char;
7130 char *value;
7131 int val_len;
7132 int newlinesize;
7133 int braces = 0;
7134
7135 var_beg = line + 1;
7136 var_end = var_beg;
7137
7138 if (*var_beg == '{') {
7139 var_beg++;
7140 var_end++;
7141 braces = 1;
7142 }
7143
7144 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7145 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7146 err_code |= ERR_ALERT | ERR_FATAL;
7147 goto next_line; /* skip current line */
7148 }
7149
7150 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7151 var_end++;
7152
7153 save_char = *var_end;
7154 *var_end = '\0';
7155 value = getenv(var_beg);
7156 *var_end = save_char;
7157 val_len = value ? strlen(value) : 0;
7158
7159 if (braces) {
7160 if (*var_end == '}') {
7161 var_end++;
7162 braces = 0;
7163 } else {
7164 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7165 err_code |= ERR_ALERT | ERR_FATAL;
7166 goto next_line; /* skip current line */
7167 }
7168 }
7169
7170 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7171
7172 /* if not enough space in thisline */
7173 if (newlinesize > linesize) {
7174 char *newline;
7175
7176 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7177 if (newline == NULL) {
7178 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7179 err_code |= ERR_ALERT | ERR_FATAL;
7180 goto next_line; /* slip current line */
7181 }
7182 /* recompute pointers if realloc returns a new pointer */
7183 if (newline != thisline) {
7184 int i;
7185 int diff;
7186
7187 for (i = 0; i <= arg; i++) {
7188 diff = args[i] - thisline;
7189 args[i] = newline + diff;
7190 }
7191
7192 diff = var_end - thisline;
7193 var_end = newline + diff;
7194 diff = end - thisline;
7195 end = newline + diff;
7196 diff = line - thisline;
7197 line = newline + diff;
7198 thisline = newline;
7199 }
7200 linesize = newlinesize;
7201 }
7202
7203 /* insert value inside the line */
7204 memmove(line + val_len, var_end, end - var_end + 1);
7205 memcpy(line, value, val_len);
7206 end += val_len - (var_end - line);
7207 line += val_len;
7208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007209 else {
7210 line++;
7211 }
7212 }
William Lallemandb2f07452015-05-12 14:27:13 +02007213
William Lallemandf9873ba2015-05-05 17:37:14 +02007214 if (dquote) {
7215 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7216 err_code |= ERR_ALERT | ERR_FATAL;
7217 }
7218
7219 if (squote) {
7220 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7221 err_code |= ERR_ALERT | ERR_FATAL;
7222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223
7224 /* empty line */
7225 if (!**args)
7226 continue;
7227
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007228 if (*line) {
7229 /* we had to stop due to too many args.
7230 * Let's terminate the string, print the offending part then cut the
7231 * last arg.
7232 */
7233 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7234 line++;
7235 *line = '\0';
7236
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007237 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007238 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007239 err_code |= ERR_ALERT | ERR_FATAL;
7240 args[arg] = line;
7241 }
7242
Willy Tarreau540abe42007-05-02 20:50:16 +02007243 /* zero out remaining args and ensure that at least one entry
7244 * is zeroed out.
7245 */
7246 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 args[arg] = line;
7248 }
7249
Willy Tarreau3842f002009-06-14 11:39:52 +02007250 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007251 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007252 char *tmp;
7253
Willy Tarreau3842f002009-06-14 11:39:52 +02007254 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007255 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007256 for (arg=0; *args[arg+1]; arg++)
7257 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007258 *tmp = '\0'; // fix the next arg to \0
7259 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007260 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007261 else if (!strcmp(args[0], "default")) {
7262 kwm = KWM_DEF;
7263 for (arg=0; *args[arg+1]; arg++)
7264 args[arg] = args[arg+1]; // shift args after inversion
7265 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007266
William Lallemand0f99e342011-10-12 17:50:54 +02007267 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7268 strcmp(args[0], "log") != 0) {
7269 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007270 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007271 }
7272
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007273 /* detect section start */
7274 list_for_each_entry(ics, &sections, list) {
7275 if (strcmp(args[0], ics->section_name) == 0) {
7276 cursection = ics->section_name;
7277 cs = ics;
7278 break;
7279 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007280 }
7281
Willy Tarreaubaaee002006-06-26 02:48:02 +02007282 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007283 if (cs)
7284 err_code |= cs->section_parser(file, linenum, args, kwm);
7285 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007286 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007288 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007289
7290 if (err_code & ERR_ABORT)
7291 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007292 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007293 free(cfg_scope);
7294 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007295 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007296 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007297 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007298 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007299}
7300
Willy Tarreau64ab6072014-09-16 12:17:36 +02007301/* This function propagates processes from frontend <from> to backend <to> so
7302 * that it is always guaranteed that a backend pointed to by a frontend is
7303 * bound to all of its processes. After that, if the target is a "listen"
7304 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007305 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007306 * checked first to ensure that <to> is already bound to all processes of
7307 * <from>, there is no risk of looping and we ensure to follow the shortest
7308 * path to the destination.
7309 *
7310 * It is possible to set <to> to NULL for the first call so that the function
7311 * takes care of visiting the initial frontend in <from>.
7312 *
7313 * It is important to note that the function relies on the fact that all names
7314 * have already been resolved.
7315 */
7316void propagate_processes(struct proxy *from, struct proxy *to)
7317{
7318 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007319
7320 if (to) {
7321 /* check whether we need to go down */
7322 if (from->bind_proc &&
7323 (from->bind_proc & to->bind_proc) == from->bind_proc)
7324 return;
7325
7326 if (!from->bind_proc && !to->bind_proc)
7327 return;
7328
7329 to->bind_proc = from->bind_proc ?
7330 (to->bind_proc | from->bind_proc) : 0;
7331
7332 /* now propagate down */
7333 from = to;
7334 }
7335
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007336 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007337 return;
7338
Willy Tarreauf6b70012014-12-18 14:00:43 +01007339 if (from->state == PR_STSTOPPED)
7340 return;
7341
Willy Tarreau64ab6072014-09-16 12:17:36 +02007342 /* default_backend */
7343 if (from->defbe.be)
7344 propagate_processes(from, from->defbe.be);
7345
7346 /* use_backend */
7347 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007348 if (rule->dynamic)
7349 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007350 to = rule->be.backend;
7351 propagate_processes(from, to);
7352 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007353}
7354
Willy Tarreaubb925012009-07-23 13:36:36 +02007355/*
7356 * Returns the error code, 0 if OK, or any combination of :
7357 * - ERR_ABORT: must abort ASAP
7358 * - ERR_FATAL: we can continue parsing but not start the service
7359 * - ERR_WARN: a warning has been emitted
7360 * - ERR_ALERT: an alert has been emitted
7361 * Only the two first ones can stop processing, the two others are just
7362 * indicators.
7363 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007364int check_config_validity()
7365{
7366 int cfgerr = 0;
7367 struct proxy *curproxy = NULL;
7368 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007369 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007370 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007371 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007372 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007373 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007374
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007375 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007376 /*
7377 * Now, check for the integrity of all that we have collected.
7378 */
7379
7380 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007381 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007382
Willy Tarreau193b8c62012-11-22 00:17:38 +01007383 if (!global.tune.max_http_hdr)
7384 global.tune.max_http_hdr = MAX_HTTP_HDR;
7385
7386 if (!global.tune.cookie_len)
7387 global.tune.cookie_len = CAPTURE_LEN;
7388
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007389 if (!global.tune.requri_len)
7390 global.tune.requri_len = REQURI_LEN;
7391
Emeric Brun96fd9262017-07-05 13:33:16 +02007392 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7393
Willy Tarreau193b8c62012-11-22 00:17:38 +01007394 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7395
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007396 /* allocate pool of resolution per resolvers */
7397 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7398 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7399 /* error message is already displayed by dns_alloc_resolution_pool() */
7400 err_code |= ERR_ALERT | ERR_ABORT;
7401 goto out;
7402 }
7403 }
7404
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007405 /* Post initialisation of the users and groups lists. */
7406 err_code = userlist_postinit();
7407 if (err_code != ERR_NONE)
7408 goto out;
7409
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007410 /* first, we will invert the proxy list order */
7411 curproxy = NULL;
7412 while (proxy) {
7413 struct proxy *next;
7414
7415 next = proxy->next;
7416 proxy->next = curproxy;
7417 curproxy = proxy;
7418 if (!next)
7419 break;
7420 proxy = next;
7421 }
7422
Willy Tarreau419ead82014-09-16 13:41:21 +02007423 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007424 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007425 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007426 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007427 struct act_rule *trule;
7428 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007429 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007430 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007431 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007432
Willy Tarreau050536d2012-10-04 08:47:34 +02007433 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007434 /* proxy ID not set, use automatic numbering with first
7435 * spare entry starting with next_pxid.
7436 */
7437 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7438 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7439 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007440 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007441 next_pxid++;
7442
Willy Tarreau55ea7572007-06-17 19:56:27 +02007443
Willy Tarreaubaaee002006-06-26 02:48:02 +02007444 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007445 /* ensure we don't keep listeners uselessly bound */
7446 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007447 free((void *)curproxy->table.peers.name);
7448 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007449 continue;
7450 }
7451
Willy Tarreau102df612014-05-07 23:56:38 +02007452 /* Check multi-process mode compatibility for the current proxy */
7453
7454 if (curproxy->bind_proc) {
7455 /* an explicit bind-process was specified, let's check how many
7456 * processes remain.
7457 */
David Carliere6c39412015-07-02 07:00:17 +00007458 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007459
7460 curproxy->bind_proc &= nbits(global.nbproc);
7461 if (!curproxy->bind_proc && nbproc == 1) {
7462 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);
7463 curproxy->bind_proc = 1;
7464 }
7465 else if (!curproxy->bind_proc && nbproc > 1) {
7466 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);
7467 curproxy->bind_proc = 0;
7468 }
7469 }
7470
Willy Tarreau3d209582014-05-09 17:06:11 +02007471 /* check and reduce the bind-proc of each listener */
7472 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7473 unsigned long mask;
7474
7475 if (!bind_conf->bind_proc)
7476 continue;
7477
7478 mask = nbits(global.nbproc);
7479 if (curproxy->bind_proc)
7480 mask &= curproxy->bind_proc;
7481 /* mask cannot be null here thanks to the previous checks */
7482
David Carliere6c39412015-07-02 07:00:17 +00007483 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007484 bind_conf->bind_proc &= mask;
7485
7486 if (!bind_conf->bind_proc && nbproc == 1) {
7487 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",
7488 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7489 bind_conf->bind_proc = mask & ~(mask - 1);
7490 }
7491 else if (!bind_conf->bind_proc && nbproc > 1) {
7492 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",
7493 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7494 bind_conf->bind_proc = 0;
7495 }
7496 }
7497
Willy Tarreauff01a212009-03-15 13:46:16 +01007498 switch (curproxy->mode) {
7499 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007500 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007501 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007502 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7503 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007504 cfgerr++;
7505 }
7506
7507 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007508 Warning("config : servers will be ignored for %s '%s'.\n",
7509 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007510 break;
7511
7512 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007513 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007514 break;
7515
7516 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007517 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007518 break;
7519 }
7520
Willy Tarreauf3934b82015-08-11 11:36:45 +02007521 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7522 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7523 proxy_type_str(curproxy), curproxy->id);
7524 err_code |= ERR_WARN;
7525 }
7526
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007527 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007528 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007529 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007530 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7531 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007532 cfgerr++;
7533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007534#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007535 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007536 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7537 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007538 cfgerr++;
7539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007540#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007541 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007542 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007544 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007545 }
7546 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007547 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007548 /* If no LB algo is set in a backend, and we're not in
7549 * transparent mode, dispatch mode nor proxy mode, we
7550 * want to use balance roundrobin by default.
7551 */
7552 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7553 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007554 }
7555 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007556
Willy Tarreau1620ec32011-08-06 17:05:02 +02007557 if (curproxy->options & PR_O_DISPATCH)
7558 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7559 else if (curproxy->options & PR_O_HTTP_PROXY)
7560 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7561 else if (curproxy->options & PR_O_TRANSP)
7562 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007563
Willy Tarreau1620ec32011-08-06 17:05:02 +02007564 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7565 if (curproxy->options & PR_O_DISABLE404) {
7566 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7567 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7568 err_code |= ERR_WARN;
7569 curproxy->options &= ~PR_O_DISABLE404;
7570 }
7571 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7572 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7573 "send-state", proxy_type_str(curproxy), curproxy->id);
7574 err_code |= ERR_WARN;
7575 curproxy->options &= ~PR_O2_CHK_SNDST;
7576 }
Willy Tarreauef781042010-01-27 11:53:01 +01007577 }
7578
Simon Horman98637e52014-06-20 12:30:16 +09007579 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7580 if (!global.external_check) {
7581 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7582 curproxy->id, "option external-check");
7583 cfgerr++;
7584 }
7585 if (!curproxy->check_command) {
7586 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7587 curproxy->id, "option external-check");
7588 cfgerr++;
7589 }
7590 }
7591
Simon Horman64e34162015-02-06 11:11:57 +09007592 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007593 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7594 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007595 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7596 "'email-alert myhostname', or 'email-alert to' "
7597 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007598 "to be present).\n",
7599 proxy_type_str(curproxy), curproxy->id);
7600 err_code |= ERR_WARN;
7601 free_email_alert(curproxy);
7602 }
7603 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007604 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007605 }
7606
Simon Horman98637e52014-06-20 12:30:16 +09007607 if (curproxy->check_command) {
7608 int clear = 0;
7609 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7610 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7611 "external-check command", proxy_type_str(curproxy), curproxy->id);
7612 err_code |= ERR_WARN;
7613 clear = 1;
7614 }
7615 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007616 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007617 curproxy->id, "external-check command");
7618 cfgerr++;
7619 }
7620 if (clear) {
7621 free(curproxy->check_command);
7622 curproxy->check_command = NULL;
7623 }
7624 }
7625
7626 if (curproxy->check_path) {
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 path", proxy_type_str(curproxy), curproxy->id);
7630 err_code |= ERR_WARN;
7631 free(curproxy->check_path);
7632 curproxy->check_path = NULL;
7633 }
7634 }
7635
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007636 /* if a default backend was specified, let's find it */
7637 if (curproxy->defbe.name) {
7638 struct proxy *target;
7639
Willy Tarreauafb39922015-05-26 12:04:09 +02007640 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007641 if (!target) {
7642 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7643 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007644 cfgerr++;
7645 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007646 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7647 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007648 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007649 } else if (target->mode != curproxy->mode &&
7650 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7651
7652 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7653 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7654 curproxy->conf.file, curproxy->conf.line,
7655 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7656 target->conf.file, target->conf.line);
7657 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007658 } else {
7659 free(curproxy->defbe.name);
7660 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007661 /* Update tot_fe_maxconn for a further fullconn's computation */
7662 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007663 /* Emit a warning if this proxy also has some servers */
7664 if (curproxy->srv) {
7665 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7666 curproxy->id);
7667 err_code |= ERR_WARN;
7668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007669 }
7670 }
7671
Emeric Brun3f783572017-01-12 11:21:28 +01007672 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7673 /* Case of listen without default backend
7674 * The curproxy will be its own default backend
7675 * so we update tot_fe_maxconn for a further
7676 * fullconn's computation */
7677 curproxy->tot_fe_maxconn += curproxy->maxconn;
7678 }
7679
Willy Tarreau55ea7572007-06-17 19:56:27 +02007680 /* find the target proxy for 'use_backend' rules */
7681 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007682 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007683 struct logformat_node *node;
7684 char *pxname;
7685
7686 /* Try to parse the string as a log format expression. If the result
7687 * of the parsing is only one entry containing a simple string, then
7688 * it's a standard string corresponding to a static rule, thus the
7689 * parsing is cancelled and be.name is restored to be resolved.
7690 */
7691 pxname = rule->be.name;
7692 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007693 curproxy->conf.args.ctx = ARGC_UBK;
7694 curproxy->conf.args.file = rule->file;
7695 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007696 err = NULL;
7697 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7698 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7699 rule->file, rule->line, pxname, err);
7700 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007701 cfgerr++;
7702 continue;
7703 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007704 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7705
7706 if (!LIST_ISEMPTY(&rule->be.expr)) {
7707 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7708 rule->dynamic = 1;
7709 free(pxname);
7710 continue;
7711 }
7712 /* simple string: free the expression and fall back to static rule */
7713 free(node->arg);
7714 free(node);
7715 }
7716
7717 rule->dynamic = 0;
7718 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719
Willy Tarreauafb39922015-05-26 12:04:09 +02007720 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007721 if (!target) {
7722 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7723 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007724 cfgerr++;
7725 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007726 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7727 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007728 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007729 } else if (target->mode != curproxy->mode &&
7730 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7731
7732 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7733 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7734 curproxy->conf.file, curproxy->conf.line,
7735 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7736 target->conf.file, target->conf.line);
7737 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007738 } else {
7739 free((void *)rule->be.name);
7740 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007741 /* For each target of switching rules, we update
7742 * their tot_fe_maxconn, except if a previous rule point
7743 * on the same backend or on the default backend */
7744 if (rule->be.backend != curproxy->defbe.be) {
7745 struct switching_rule *swrule;
7746
7747 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7748 if (rule == swrule) {
7749 target->tot_fe_maxconn += curproxy->maxconn;
7750 break;
7751 }
7752 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7753 /* there is multiple ref of this backend */
7754 break;
7755 }
7756 }
7757 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007758 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007759 }
7760
Willy Tarreau64ab6072014-09-16 12:17:36 +02007761 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007762 list_for_each_entry(srule, &curproxy->server_rules, list) {
7763 struct server *target = findserver(curproxy, srule->srv.name);
7764
7765 if (!target) {
7766 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7767 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7768 cfgerr++;
7769 continue;
7770 }
7771 free((void *)srule->srv.name);
7772 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007773 }
7774
Emeric Brunb982a3d2010-01-04 15:45:53 +01007775 /* find the target table for 'stick' rules */
7776 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7777 struct proxy *target;
7778
Emeric Brun1d33b292010-01-04 15:47:17 +01007779 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7780 if (mrule->flags & STK_IS_STORE)
7781 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7782
Emeric Brunb982a3d2010-01-04 15:45:53 +01007783 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007784 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007785 else
7786 target = curproxy;
7787
7788 if (!target) {
7789 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7790 curproxy->id, mrule->table.name);
7791 cfgerr++;
7792 }
7793 else if (target->table.size == 0) {
7794 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7795 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7796 cfgerr++;
7797 }
Willy Tarreau12785782012-04-27 21:37:17 +02007798 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7799 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007800 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7801 cfgerr++;
7802 }
7803 else {
7804 free((void *)mrule->table.name);
7805 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007806 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007807 }
7808 }
7809
7810 /* find the target table for 'store response' rules */
7811 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7812 struct proxy *target;
7813
Emeric Brun1d33b292010-01-04 15:47:17 +01007814 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7815
Emeric Brunb982a3d2010-01-04 15:45:53 +01007816 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007817 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007818 else
7819 target = curproxy;
7820
7821 if (!target) {
7822 Alert("Proxy '%s': unable to find store table '%s'.\n",
7823 curproxy->id, mrule->table.name);
7824 cfgerr++;
7825 }
7826 else if (target->table.size == 0) {
7827 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7828 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7829 cfgerr++;
7830 }
Willy Tarreau12785782012-04-27 21:37:17 +02007831 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7832 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007833 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7834 cfgerr++;
7835 }
7836 else {
7837 free((void *)mrule->table.name);
7838 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007839 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 }
7841 }
7842
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007843 /* find the target table for 'tcp-request' layer 4 rules */
7844 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7845 struct proxy *target;
7846
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007847 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007848 continue;
7849
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007850 if (trule->arg.trk_ctr.table.n)
7851 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007852 else
7853 target = curproxy;
7854
7855 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007856 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007857 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007858 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007859 cfgerr++;
7860 }
7861 else if (target->table.size == 0) {
7862 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007863 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007864 cfgerr++;
7865 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007866 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007867 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007868 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007869 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007870 cfgerr++;
7871 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007872 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007873 free(trule->arg.trk_ctr.table.n);
7874 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007875 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007876 * to pass a list of counters to track and allocate them right here using
7877 * stktable_alloc_data_type().
7878 */
7879 }
7880 }
7881
Willy Tarreau620408f2016-10-21 16:37:51 +02007882 /* find the target table for 'tcp-request' layer 5 rules */
7883 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7884 struct proxy *target;
7885
7886 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7887 continue;
7888
7889 if (trule->arg.trk_ctr.table.n)
7890 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7891 else
7892 target = curproxy;
7893
7894 if (!target) {
7895 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7896 curproxy->id, trule->arg.trk_ctr.table.n,
7897 tcp_trk_idx(trule->action));
7898 cfgerr++;
7899 }
7900 else if (target->table.size == 0) {
7901 Alert("Proxy '%s': table '%s' used but not configured.\n",
7902 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7903 cfgerr++;
7904 }
7905 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7906 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7907 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7908 tcp_trk_idx(trule->action));
7909 cfgerr++;
7910 }
7911 else {
7912 free(trule->arg.trk_ctr.table.n);
7913 trule->arg.trk_ctr.table.t = &target->table;
7914 /* Note: if we decide to enhance the track-sc syntax, we may be able
7915 * to pass a list of counters to track and allocate them right here using
7916 * stktable_alloc_data_type().
7917 */
7918 }
7919 }
7920
Willy Tarreaud1f96522010-08-03 19:34:32 +02007921 /* find the target table for 'tcp-request' layer 6 rules */
7922 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7923 struct proxy *target;
7924
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007925 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007926 continue;
7927
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007928 if (trule->arg.trk_ctr.table.n)
7929 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007930 else
7931 target = curproxy;
7932
7933 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007934 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007935 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007936 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007937 cfgerr++;
7938 }
7939 else if (target->table.size == 0) {
7940 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007941 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007942 cfgerr++;
7943 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007944 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007945 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007946 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007947 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007948 cfgerr++;
7949 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007950 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007951 free(trule->arg.trk_ctr.table.n);
7952 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007953 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007954 * to pass a list of counters to track and allocate them right here using
7955 * stktable_alloc_data_type().
7956 */
7957 }
7958 }
7959
Baptiste Assmanne9544932015-11-03 23:31:35 +01007960 /* parse http-request capture rules to ensure id really exists */
7961 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7962 if (hrqrule->action != ACT_CUSTOM ||
7963 hrqrule->action_ptr != http_action_req_capture_by_id)
7964 continue;
7965
7966 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7967 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7968 curproxy->id, hrqrule->arg.capid.idx);
7969 cfgerr++;
7970 }
7971 }
7972
7973 /* parse http-response capture rules to ensure id really exists */
7974 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7975 if (hrqrule->action != ACT_CUSTOM ||
7976 hrqrule->action_ptr != http_action_res_capture_by_id)
7977 continue;
7978
7979 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7980 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7981 curproxy->id, hrqrule->arg.capid.idx);
7982 cfgerr++;
7983 }
7984 }
7985
Willy Tarreau09448f72014-06-25 18:12:15 +02007986 /* find the target table for 'http-request' layer 7 rules */
7987 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7988 struct proxy *target;
7989
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007990 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007991 continue;
7992
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007993 if (hrqrule->arg.trk_ctr.table.n)
7994 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007995 else
7996 target = curproxy;
7997
7998 if (!target) {
7999 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008000 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008001 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008002 cfgerr++;
8003 }
8004 else if (target->table.size == 0) {
8005 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008006 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008007 cfgerr++;
8008 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008009 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008010 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008011 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008012 http_trk_idx(hrqrule->action));
8013 cfgerr++;
8014 }
8015 else {
8016 free(hrqrule->arg.trk_ctr.table.n);
8017 hrqrule->arg.trk_ctr.table.t = &target->table;
8018 /* Note: if we decide to enhance the track-sc syntax, we may be able
8019 * to pass a list of counters to track and allocate them right here using
8020 * stktable_alloc_data_type().
8021 */
8022 }
8023 }
8024
8025 /* find the target table for 'http-response' layer 7 rules */
8026 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8027 struct proxy *target;
8028
8029 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8030 continue;
8031
8032 if (hrqrule->arg.trk_ctr.table.n)
8033 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8034 else
8035 target = curproxy;
8036
8037 if (!target) {
8038 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8039 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8040 http_trk_idx(hrqrule->action));
8041 cfgerr++;
8042 }
8043 else if (target->table.size == 0) {
8044 Alert("Proxy '%s': table '%s' used but not configured.\n",
8045 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8046 cfgerr++;
8047 }
8048 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8049 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8050 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8051 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008052 cfgerr++;
8053 }
8054 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008055 free(hrqrule->arg.trk_ctr.table.n);
8056 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008057 /* Note: if we decide to enhance the track-sc syntax, we may be able
8058 * to pass a list of counters to track and allocate them right here using
8059 * stktable_alloc_data_type().
8060 */
8061 }
8062 }
8063
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008064 /* move any "block" rules at the beginning of the http-request rules */
8065 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8066 /* insert block_rules into http_req_rules at the beginning */
8067 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8068 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8069 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8070 curproxy->http_req_rules.n = curproxy->block_rules.n;
8071 LIST_INIT(&curproxy->block_rules);
8072 }
8073
Emeric Brun32da3c42010-09-23 18:39:19 +02008074 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008075 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008076
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008077 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008078 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8079 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008080 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008081 break;
8082 }
8083 }
8084
8085 if (!curpeers) {
8086 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8087 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008088 free((void *)curproxy->table.peers.name);
8089 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008090 cfgerr++;
8091 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008092 else if (curpeers->state == PR_STSTOPPED) {
8093 /* silently disable this peers section */
8094 curproxy->table.peers.p = NULL;
8095 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008096 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008097 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8098 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008099 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008100 cfgerr++;
8101 }
8102 }
8103
Simon Horman9dc49962015-01-30 11:22:59 +09008104
8105 if (curproxy->email_alert.mailers.name) {
8106 struct mailers *curmailers = mailers;
8107
8108 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8109 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8110 free(curproxy->email_alert.mailers.name);
8111 curproxy->email_alert.mailers.m = curmailers;
8112 curmailers->users++;
8113 break;
8114 }
8115 }
8116
8117 if (!curmailers) {
8118 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8119 curproxy->id, curproxy->email_alert.mailers.name);
8120 free_email_alert(curproxy);
8121 cfgerr++;
8122 }
8123 }
8124
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008125 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008126 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008127 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8128 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8129 "proxy", curproxy->id);
8130 cfgerr++;
8131 goto out_uri_auth_compat;
8132 }
8133
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008134 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008135 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008136 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008137 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008138
Willy Tarreau95fa4692010-02-01 13:05:50 +01008139 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8140 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008141
8142 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008143 uri_auth_compat_req[i++] = "realm";
8144 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8145 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008146
Willy Tarreau95fa4692010-02-01 13:05:50 +01008147 uri_auth_compat_req[i++] = "unless";
8148 uri_auth_compat_req[i++] = "{";
8149 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8150 uri_auth_compat_req[i++] = "}";
8151 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008152
Willy Tarreauff011f22011-01-06 17:51:27 +01008153 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8154 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008155 cfgerr++;
8156 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008157 }
8158
Willy Tarreauff011f22011-01-06 17:51:27 +01008159 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008160
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008161 if (curproxy->uri_auth->auth_realm) {
8162 free(curproxy->uri_auth->auth_realm);
8163 curproxy->uri_auth->auth_realm = NULL;
8164 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008165
8166 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008167 }
8168out_uri_auth_compat:
8169
Dragan Dosen43885c72015-10-01 13:18:13 +02008170 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008171 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008172 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8173 if (!curproxy->conf.logformat_sd_string) {
8174 /* set the default logformat_sd_string */
8175 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8176 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008177 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008178 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008179 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008180
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008181 /* compile the log format */
8182 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008183 if (curproxy->conf.logformat_string != default_http_log_format &&
8184 curproxy->conf.logformat_string != default_tcp_log_format &&
8185 curproxy->conf.logformat_string != clf_http_log_format)
8186 free(curproxy->conf.logformat_string);
8187 curproxy->conf.logformat_string = NULL;
8188 free(curproxy->conf.lfs_file);
8189 curproxy->conf.lfs_file = NULL;
8190 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008191
8192 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8193 free(curproxy->conf.logformat_sd_string);
8194 curproxy->conf.logformat_sd_string = NULL;
8195 free(curproxy->conf.lfsd_file);
8196 curproxy->conf.lfsd_file = NULL;
8197 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008198 }
8199
Willy Tarreau62a61232013-04-12 18:13:46 +02008200 if (curproxy->conf.logformat_string) {
8201 curproxy->conf.args.ctx = ARGC_LOG;
8202 curproxy->conf.args.file = curproxy->conf.lfs_file;
8203 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008204 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008205 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008206 SMP_VAL_FE_LOG_END, &err)) {
8207 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8208 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8209 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008210 cfgerr++;
8211 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008212 curproxy->conf.args.file = NULL;
8213 curproxy->conf.args.line = 0;
8214 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008215
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008216 if (curproxy->conf.logformat_sd_string) {
8217 curproxy->conf.args.ctx = ARGC_LOGSD;
8218 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8219 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008220 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008221 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 +01008222 SMP_VAL_FE_LOG_END, &err)) {
8223 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8224 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8225 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008226 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008227 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8228 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8229 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8230 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008231 cfgerr++;
8232 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008233 curproxy->conf.args.file = NULL;
8234 curproxy->conf.args.line = 0;
8235 }
8236
Willy Tarreau62a61232013-04-12 18:13:46 +02008237 if (curproxy->conf.uniqueid_format_string) {
8238 curproxy->conf.args.ctx = ARGC_UIF;
8239 curproxy->conf.args.file = curproxy->conf.uif_file;
8240 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008241 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008242 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 +01008243 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8244 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8245 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8246 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008247 cfgerr++;
8248 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008249 curproxy->conf.args.file = NULL;
8250 curproxy->conf.args.line = 0;
8251 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008252
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008253 /* only now we can check if some args remain unresolved.
8254 * This must be done after the users and groups resolution.
8255 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008256 cfgerr += smp_resolve_args(curproxy);
8257 if (!cfgerr)
8258 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008259
Willy Tarreau2738a142006-07-08 17:28:09 +02008260 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008261 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008262 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008263 (!curproxy->timeout.connect ||
8264 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008265 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008266 " | While not properly invalid, you will certainly encounter various problems\n"
8267 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008268 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008269 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008270 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008271 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008272
Willy Tarreau1fa31262007-12-03 00:36:16 +01008273 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8274 * We must still support older configurations, so let's find out whether those
8275 * parameters have been set or must be copied from contimeouts.
8276 */
8277 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008278 if (!curproxy->timeout.tarpit ||
8279 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008280 /* tarpit timeout not set. We search in the following order:
8281 * default.tarpit, curr.connect, default.connect.
8282 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008283 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008284 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008285 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008286 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008287 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008288 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008289 }
8290 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008291 (!curproxy->timeout.queue ||
8292 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008293 /* queue timeout not set. We search in the following order:
8294 * default.queue, curr.connect, default.connect.
8295 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008296 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008297 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008298 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008299 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008300 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008301 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008302 }
8303 }
8304
Willy Tarreau1620ec32011-08-06 17:05:02 +02008305 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008306 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008307 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008308 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008309 }
8310
Willy Tarreau215663d2014-06-13 18:30:23 +02008311 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8312 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8313 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8314 proxy_type_str(curproxy), curproxy->id);
8315 err_code |= ERR_WARN;
8316 }
8317
Willy Tarreau193b8c62012-11-22 00:17:38 +01008318 /* ensure that cookie capture length is not too large */
8319 if (curproxy->capture_len >= global.tune.cookie_len) {
8320 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8321 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8322 err_code |= ERR_WARN;
8323 curproxy->capture_len = global.tune.cookie_len - 1;
8324 }
8325
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008326 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008327 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008328 curproxy->req_cap_pool = create_pool("ptrcap",
8329 curproxy->nb_req_cap * sizeof(char *),
8330 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008331 }
8332
8333 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008334 curproxy->rsp_cap_pool = create_pool("ptrcap",
8335 curproxy->nb_rsp_cap * sizeof(char *),
8336 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008337 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008338
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008339 switch (curproxy->load_server_state_from_file) {
8340 case PR_SRV_STATE_FILE_UNSPEC:
8341 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8342 break;
8343 case PR_SRV_STATE_FILE_GLOBAL:
8344 if (!global.server_state_file) {
8345 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",
8346 curproxy->id);
8347 err_code |= ERR_WARN;
8348 }
8349 break;
8350 }
8351
Willy Tarreaubaaee002006-06-26 02:48:02 +02008352 /* first, we will invert the servers list order */
8353 newsrv = NULL;
8354 while (curproxy->srv) {
8355 struct server *next;
8356
8357 next = curproxy->srv->next;
8358 curproxy->srv->next = newsrv;
8359 newsrv = curproxy->srv;
8360 if (!next)
8361 break;
8362 curproxy->srv = next;
8363 }
8364
Willy Tarreau17edc812014-01-03 12:14:34 +01008365 /* Check that no server name conflicts. This causes trouble in the stats.
8366 * We only emit a warning for the first conflict affecting each server,
8367 * in order to avoid combinatory explosion if all servers have the same
8368 * name. We do that only for servers which do not have an explicit ID,
8369 * because these IDs were made also for distinguishing them and we don't
8370 * want to annoy people who correctly manage them.
8371 */
8372 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8373 struct server *other_srv;
8374
8375 if (newsrv->puid)
8376 continue;
8377
8378 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8379 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8380 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8381 newsrv->conf.file, newsrv->conf.line,
8382 proxy_type_str(curproxy), curproxy->id,
8383 newsrv->id, other_srv->conf.line);
8384 break;
8385 }
8386 }
8387 }
8388
Willy Tarreaudd701652010-05-25 23:03:02 +02008389 /* assign automatic UIDs to servers which don't have one yet */
8390 next_id = 1;
8391 newsrv = curproxy->srv;
8392 while (newsrv != NULL) {
8393 if (!newsrv->puid) {
8394 /* server ID not set, use automatic numbering with first
8395 * spare entry starting with next_svid.
8396 */
8397 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8398 newsrv->conf.id.key = newsrv->puid = next_id;
8399 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8400 }
8401 next_id++;
8402 newsrv = newsrv->next;
8403 }
8404
Willy Tarreau20697042007-11-15 23:26:18 +01008405 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008406 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008407
Willy Tarreau62c3be22012-01-20 13:12:32 +01008408 /*
8409 * If this server supports a maxconn parameter, it needs a dedicated
8410 * tasks to fill the emptied slots when a connection leaves.
8411 * Also, resolve deferred tracking dependency if needed.
8412 */
8413 newsrv = curproxy->srv;
8414 while (newsrv != NULL) {
8415 if (newsrv->minconn > newsrv->maxconn) {
8416 /* Only 'minconn' was specified, or it was higher than or equal
8417 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8418 * this will avoid further useless expensive computations.
8419 */
8420 newsrv->maxconn = newsrv->minconn;
8421 } else if (newsrv->maxconn && !newsrv->minconn) {
8422 /* minconn was not specified, so we set it to maxconn */
8423 newsrv->minconn = newsrv->maxconn;
8424 }
8425
Willy Tarreau17d45382016-12-22 21:16:08 +01008426 /* this will also properly set the transport layer for prod and checks */
8427 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8428 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8429 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8430 }
Emeric Brun94324a42012-10-11 14:00:19 +02008431
Willy Tarreau2f075e92013-12-03 11:11:34 +01008432 /* set the check type on the server */
8433 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8434
Willy Tarreau62c3be22012-01-20 13:12:32 +01008435 if (newsrv->trackit) {
8436 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008437 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008438 char *pname, *sname;
8439
8440 pname = newsrv->trackit;
8441 sname = strrchr(pname, '/');
8442
8443 if (sname)
8444 *sname++ = '\0';
8445 else {
8446 sname = pname;
8447 pname = NULL;
8448 }
8449
8450 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008451 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008452 if (!px) {
8453 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8454 proxy_type_str(curproxy), curproxy->id,
8455 newsrv->id, pname);
8456 cfgerr++;
8457 goto next_srv;
8458 }
8459 } else
8460 px = curproxy;
8461
8462 srv = findserver(px, sname);
8463 if (!srv) {
8464 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8465 proxy_type_str(curproxy), curproxy->id,
8466 newsrv->id, sname);
8467 cfgerr++;
8468 goto next_srv;
8469 }
8470
Willy Tarreau32091232014-05-16 13:52:00 +02008471 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8472 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8473 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008474 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008475 "tracking as it does not have any check nor agent enabled.\n",
8476 proxy_type_str(curproxy), curproxy->id,
8477 newsrv->id, px->id, srv->id);
8478 cfgerr++;
8479 goto next_srv;
8480 }
8481
8482 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8483
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008484 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008485 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8486 "belongs to a tracking chain looping back to %s/%s.\n",
8487 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008488 newsrv->id, px->id, srv->id, px->id,
8489 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008490 cfgerr++;
8491 goto next_srv;
8492 }
8493
8494 if (curproxy != px &&
8495 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8496 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8497 "tracking: disable-on-404 option inconsistency.\n",
8498 proxy_type_str(curproxy), curproxy->id,
8499 newsrv->id, px->id, srv->id);
8500 cfgerr++;
8501 goto next_srv;
8502 }
8503
Willy Tarreau62c3be22012-01-20 13:12:32 +01008504 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008505 newsrv->tracknext = srv->trackers;
8506 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008507
8508 free(newsrv->trackit);
8509 newsrv->trackit = NULL;
8510 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008511
8512 /*
8513 * resolve server's resolvers name and update the resolvers pointer
8514 * accordingly
8515 */
8516 if (newsrv->resolvers_id) {
8517 struct dns_resolvers *curr_resolvers;
8518 int found;
8519
8520 found = 0;
8521 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8522 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8523 found = 1;
8524 break;
8525 }
8526 }
8527
8528 if (!found) {
8529 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8530 proxy_type_str(curproxy), curproxy->id,
8531 newsrv->id, newsrv->resolvers_id);
8532 cfgerr++;
8533 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008534 if (newsrv->srvrq) {
8535 if (!newsrv->srvrq->resolvers) {
8536 newsrv->srvrq->resolvers = curr_resolvers;
8537 if (dns_link_resolution(newsrv->srvrq,
8538 OBJ_TYPE_SRVRQ, NULL) != 0) {
8539 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8540 proxy_type_str(curproxy), curproxy->id,
8541 newsrv->id);
8542 cfgerr++;
8543 }
8544 }
8545
8546 }
8547 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008548 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008549 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8550 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8551 proxy_type_str(curproxy), curproxy->id,
8552 newsrv->id);
8553 cfgerr++;
8554 }
8555 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008556 }
8557 }
8558 else {
8559 /* if no resolvers section associated to this server
8560 * we can clean up the associated resolution structure
8561 */
8562 if (newsrv->resolution) {
8563 free(newsrv->resolution->hostname_dn);
8564 newsrv->resolution->hostname_dn = NULL;
8565 free(newsrv->resolution);
8566 newsrv->resolution = NULL;
8567 }
8568 }
8569
Willy Tarreau62c3be22012-01-20 13:12:32 +01008570 next_srv:
8571 newsrv = newsrv->next;
8572 }
8573
Olivier Houchard4e694042017-03-14 20:01:29 +01008574 /*
8575 * Try to generate dynamic cookies for servers now.
8576 * It couldn't be done earlier, since at the time we parsed
8577 * the server line, we may not have known yet that we
8578 * should use dynamic cookies, or the secret key may not
8579 * have been provided yet.
8580 */
8581 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8582 newsrv = curproxy->srv;
8583 while (newsrv != NULL) {
8584 srv_set_dyncookie(newsrv);
8585 newsrv = newsrv->next;
8586 }
8587
8588 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008589 /* We have to initialize the server lookup mechanism depending
8590 * on what LB algorithm was choosen.
8591 */
8592
8593 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8594 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8595 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008596 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8597 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8598 init_server_map(curproxy);
8599 } else {
8600 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8601 fwrr_init_server_groups(curproxy);
8602 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008603 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008604
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008605 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008606 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8607 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8608 fwlc_init_server_tree(curproxy);
8609 } else {
8610 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8611 fas_init_server_tree(curproxy);
8612 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008613 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008614
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008615 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008616 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8617 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8618 chash_init_server_tree(curproxy);
8619 } else {
8620 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8621 init_server_map(curproxy);
8622 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008623 break;
8624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008625
8626 if (curproxy->options & PR_O_LOGASAP)
8627 curproxy->to_log &= ~LW_BYTES;
8628
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008629 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008630 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8631 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008632 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8633 proxy_type_str(curproxy), curproxy->id);
8634 err_code |= ERR_WARN;
8635 }
8636
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008637 if (curproxy->mode != PR_MODE_HTTP) {
8638 int optnum;
8639
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008640 if (curproxy->uri_auth) {
8641 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8642 proxy_type_str(curproxy), curproxy->id);
8643 err_code |= ERR_WARN;
8644 curproxy->uri_auth = NULL;
8645 }
8646
Willy Tarreaude7dc882017-03-10 11:49:21 +01008647 if (curproxy->capture_name) {
8648 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8649 proxy_type_str(curproxy), curproxy->id);
8650 err_code |= ERR_WARN;
8651 }
8652
8653 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8654 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8655 proxy_type_str(curproxy), curproxy->id);
8656 err_code |= ERR_WARN;
8657 }
8658
8659 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8660 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8661 proxy_type_str(curproxy), curproxy->id);
8662 err_code |= ERR_WARN;
8663 }
8664
8665 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8666 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8667 proxy_type_str(curproxy), curproxy->id);
8668 err_code |= ERR_WARN;
8669 }
8670
8671 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8672 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8673 proxy_type_str(curproxy), curproxy->id);
8674 err_code |= ERR_WARN;
8675 }
8676
Willy Tarreau87cf5142011-08-19 22:57:24 +02008677 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008678 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8679 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8680 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008681 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008682 }
8683
8684 if (curproxy->options & PR_O_ORGTO) {
8685 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8686 "originalto", proxy_type_str(curproxy), curproxy->id);
8687 err_code |= ERR_WARN;
8688 curproxy->options &= ~PR_O_ORGTO;
8689 }
8690
8691 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8692 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8693 (curproxy->cap & cfg_opts[optnum].cap) &&
8694 (curproxy->options & cfg_opts[optnum].val)) {
8695 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8696 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8697 err_code |= ERR_WARN;
8698 curproxy->options &= ~cfg_opts[optnum].val;
8699 }
8700 }
8701
8702 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8703 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8704 (curproxy->cap & cfg_opts2[optnum].cap) &&
8705 (curproxy->options2 & cfg_opts2[optnum].val)) {
8706 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8707 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8708 err_code |= ERR_WARN;
8709 curproxy->options2 &= ~cfg_opts2[optnum].val;
8710 }
8711 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008712
Willy Tarreau29fbe512015-08-20 19:35:14 +02008713#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008714 if (curproxy->conn_src.bind_hdr_occ) {
8715 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008716 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008717 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008718 err_code |= ERR_WARN;
8719 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008720#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008721 }
8722
Willy Tarreaubaaee002006-06-26 02:48:02 +02008723 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008724 * ensure that we're not cross-dressing a TCP server into HTTP.
8725 */
8726 newsrv = curproxy->srv;
8727 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008728 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008729 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8730 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008731 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008732 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008733
Willy Tarreau0cec3312011-10-31 13:49:26 +01008734 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8735 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8736 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8737 err_code |= ERR_WARN;
8738 }
8739
Willy Tarreauc93cd162014-05-13 15:54:22 +02008740 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008741 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8742 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8743 err_code |= ERR_WARN;
8744 }
8745
Willy Tarreau29fbe512015-08-20 19:35:14 +02008746#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008747 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8748 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008749 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 +01008750 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008751 err_code |= ERR_WARN;
8752 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008753#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008754
8755 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8756 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8757 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8758 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8759 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8760 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",
8761 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8762 err_code |= ERR_WARN;
8763 }
8764
8765
8766 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8767 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",
8768 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8769 err_code |= ERR_WARN;
8770 }
8771 }
8772
Willy Tarreau21d2af32008-02-14 20:25:24 +01008773 newsrv = newsrv->next;
8774 }
8775
Willy Tarreaue42bd962014-09-16 16:21:19 +02008776 /* check if we have a frontend with "tcp-request content" looking at L7
8777 * with no inspect-delay
8778 */
8779 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8780 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008781 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008782 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008783 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008784 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008785 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008786 break;
8787 }
8788
8789 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8790 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8791 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8792 " This means that these rules will randomly find their contents. This can be fixed by"
8793 " setting the tcp-request inspect-delay.\n",
8794 proxy_type_str(curproxy), curproxy->id);
8795 err_code |= ERR_WARN;
8796 }
8797 }
8798
Christopher Fauletd7c91962015-04-30 11:48:27 +02008799 /* Check filter configuration, if any */
8800 cfgerr += flt_check(curproxy);
8801
Willy Tarreauc1a21672009-08-16 22:37:44 +02008802 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008803 if (!curproxy->accept)
8804 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008805
Willy Tarreauc1a21672009-08-16 22:37:44 +02008806 if (curproxy->tcp_req.inspect_delay ||
8807 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008808 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008809
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008810 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008811 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008812 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008813 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008814
8815 /* both TCP and HTTP must check switching rules */
8816 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008817
8818 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008819 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008820 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8821 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 +01008822 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008823 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8824 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008825 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008826 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008827 }
8828
8829 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008830 if (curproxy->tcp_req.inspect_delay ||
8831 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8832 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8833
Emeric Brun97679e72010-09-23 17:56:44 +02008834 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8835 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8836
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008837 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008838 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008839 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008840 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008841
8842 /* If the backend does requires RDP cookie persistence, we have to
8843 * enable the corresponding analyser.
8844 */
8845 if (curproxy->options2 & PR_O2_RDPC_PRST)
8846 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008847
8848 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008849 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008850 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8851 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 +01008852 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008853 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8854 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008855 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008856 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008857 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008858 }
8859
8860 /***********************************************************/
8861 /* At this point, target names have already been resolved. */
8862 /***********************************************************/
8863
8864 /* Check multi-process mode compatibility */
8865
8866 if (global.nbproc > 1 && global.stats_fe) {
8867 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8868 unsigned long mask;
8869
8870 mask = nbits(global.nbproc);
8871 if (global.stats_fe->bind_proc)
8872 mask &= global.stats_fe->bind_proc;
8873
8874 if (bind_conf->bind_proc)
8875 mask &= bind_conf->bind_proc;
8876
8877 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008878 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008879 break;
8880 }
8881 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8882 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");
8883 }
8884 }
8885
8886 /* Make each frontend inherit bind-process from its listeners when not specified. */
8887 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8888 if (curproxy->bind_proc)
8889 continue;
8890
8891 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8892 unsigned long mask;
8893
Willy Tarreaue428b082015-05-04 21:57:58 +02008894 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008895 curproxy->bind_proc |= mask;
8896 }
8897
8898 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008899 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008900 }
8901
8902 if (global.stats_fe) {
8903 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8904 unsigned long mask;
8905
Cyril Bonté06181952016-02-24 00:14:54 +01008906 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008907 global.stats_fe->bind_proc |= mask;
8908 }
8909 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008910 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008911 }
8912
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008913 /* propagate bindings from frontends to backends. Don't do it if there
8914 * are any fatal errors as we must not call it with unresolved proxies.
8915 */
8916 if (!cfgerr) {
8917 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8918 if (curproxy->cap & PR_CAP_FE)
8919 propagate_processes(curproxy, NULL);
8920 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008921 }
8922
8923 /* Bind each unbound backend to all processes when not specified. */
8924 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8925 if (curproxy->bind_proc)
8926 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008927 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008928 }
8929
8930 /*******************************************************/
8931 /* At this step, all proxies have a non-null bind_proc */
8932 /*******************************************************/
8933
8934 /* perform the final checks before creating tasks */
8935
8936 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8937 struct listener *listener;
8938 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008939
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008940 /* Configure SSL for each bind line.
8941 * Note: if configuration fails at some point, the ->ctx member
8942 * remains NULL so that listeners can later detach.
8943 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008944 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008945 if (bind_conf->xprt->prepare_bind_conf &&
8946 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008947 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008948 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008949
Willy Tarreaue6b98942007-10-29 01:09:36 +01008950 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008951 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008952 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008953 int nbproc;
8954
8955 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008956 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008957 nbits(global.nbproc));
8958
8959 if (!nbproc) /* no intersection between listener and frontend */
8960 nbproc = 1;
8961
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008962 if (!listener->luid) {
8963 /* listener ID not set, use automatic numbering with first
8964 * spare entry starting with next_luid.
8965 */
8966 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8967 listener->conf.id.key = listener->luid = next_id;
8968 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008969 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008970 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008971
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008972 /* enable separate counters */
8973 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008974 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008975 if (!listener->name)
8976 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008977 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008978
Willy Tarreaue6b98942007-10-29 01:09:36 +01008979 if (curproxy->options & PR_O_TCP_NOLING)
8980 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008981 if (!listener->maxconn)
8982 listener->maxconn = curproxy->maxconn;
8983 if (!listener->backlog)
8984 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008985 if (!listener->maxaccept)
8986 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8987
8988 /* we want to have an optimal behaviour on single process mode to
8989 * maximize the work at once, but in multi-process we want to keep
8990 * some fairness between processes, so we target half of the max
8991 * number of events to be balanced over all the processes the proxy
8992 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8993 * used to disable the limit.
8994 */
8995 if (listener->maxaccept > 0) {
8996 if (nbproc > 1)
8997 listener->maxaccept = (listener->maxaccept + 1) / 2;
8998 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8999 }
9000
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009001 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009002 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009003 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009004
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009005 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009006 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009007
Willy Tarreau620408f2016-10-21 16:37:51 +02009008 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9009 listener->options |= LI_O_TCP_L5_RULES;
9010
Willy Tarreaude3041d2010-05-31 10:56:17 +02009011 if (curproxy->mon_mask.s_addr)
9012 listener->options |= LI_O_CHK_MONNET;
9013
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009014 /* smart accept mode is automatic in HTTP mode */
9015 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009016 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009017 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9018 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009019 }
9020
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009021 /* Release unused SSL configs */
9022 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009023 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9024 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009025 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009026
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009027 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009028 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009029 int count, maxproc = 0;
9030
9031 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009032 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009033 if (count > maxproc)
9034 maxproc = count;
9035 }
9036 /* backends have 0, frontends have 1 or more */
9037 if (maxproc != 1)
9038 Warning("Proxy '%s': in multi-process mode, stats will be"
9039 " limited to process assigned to the current request.\n",
9040 curproxy->id);
9041
Willy Tarreau102df612014-05-07 23:56:38 +02009042 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9043 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9044 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009045 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009046 }
Willy Tarreau102df612014-05-07 23:56:38 +02009047 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9048 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9049 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009050 }
9051 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009052
9053 /* create the task associated with the proxy */
9054 curproxy->task = task_new();
9055 if (curproxy->task) {
9056 curproxy->task->context = curproxy;
9057 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009058 } else {
9059 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9060 curproxy->id);
9061 cfgerr++;
9062 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009063 }
9064
Willy Tarreaufbb78422011-06-05 15:38:35 +02009065 /* automatically compute fullconn if not set. We must not do it in the
9066 * loop above because cross-references are not yet fully resolved.
9067 */
9068 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9069 /* If <fullconn> is not set, let's set it to 10% of the sum of
9070 * the possible incoming frontend's maxconns.
9071 */
9072 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009073 /* we have the sum of the maxconns in <total>. We only
9074 * keep 10% of that sum to set the default fullconn, with
9075 * a hard minimum of 1 (to avoid a divide by zero).
9076 */
Emeric Brun3f783572017-01-12 11:21:28 +01009077 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009078 if (!curproxy->fullconn)
9079 curproxy->fullconn = 1;
9080 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009081 }
9082
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009083 /*
9084 * Recount currently required checks.
9085 */
9086
9087 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9088 int optnum;
9089
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009090 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9091 if (curproxy->options & cfg_opts[optnum].val)
9092 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009093
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009094 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9095 if (curproxy->options2 & cfg_opts2[optnum].val)
9096 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009097 }
9098
Willy Tarreau0fca4832015-05-01 19:12:05 +02009099 /* compute the required process bindings for the peers */
9100 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9101 if (curproxy->table.peers.p)
9102 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9103
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009104 if (cfg_peers) {
9105 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009106 struct peer *p, *pb;
9107
Willy Tarreau1e273012015-05-01 19:15:17 +02009108 /* Remove all peers sections which don't have a valid listener,
9109 * which are not used by any table, or which are bound to more
9110 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009111 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009112 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009113 while (*last) {
9114 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009115
9116 if (curpeers->state == PR_STSTOPPED) {
9117 /* the "disabled" keyword was present */
9118 if (curpeers->peers_fe)
9119 stop_proxy(curpeers->peers_fe);
9120 curpeers->peers_fe = NULL;
9121 }
9122 else if (!curpeers->peers_fe) {
9123 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9124 curpeers->id, localpeer);
9125 }
David Carliere6c39412015-07-02 07:00:17 +00009126 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009127 /* either it's totally stopped or too much used */
9128 if (curpeers->peers_fe->bind_proc) {
9129 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009130 "running in different processes (%d different ones). "
9131 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009132 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009133 cfgerr++;
9134 }
9135 stop_proxy(curpeers->peers_fe);
9136 curpeers->peers_fe = NULL;
9137 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009138 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009139 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009140 last = &curpeers->next;
9141 continue;
9142 }
9143
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009144 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009145 p = curpeers->remote;
9146 while (p) {
9147 pb = p->next;
9148 free(p->id);
9149 free(p);
9150 p = pb;
9151 }
9152
9153 /* Destroy and unlink this curpeers section.
9154 * Note: curpeers is backed up into *last.
9155 */
9156 free(curpeers->id);
9157 curpeers = curpeers->next;
9158 free(*last);
9159 *last = curpeers;
9160 }
9161 }
9162
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009163 /* initialize stick-tables on backend capable proxies. This must not
9164 * be done earlier because the data size may be discovered while parsing
9165 * other proxies.
9166 */
9167 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9168 if (curproxy->state == PR_STSTOPPED)
9169 continue;
9170
9171 if (!stktable_init(&curproxy->table)) {
9172 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9173 cfgerr++;
9174 }
9175 }
9176
Simon Horman0d16a402015-01-30 11:22:58 +09009177 if (mailers) {
9178 struct mailers *curmailers = mailers, **last;
9179 struct mailer *m, *mb;
9180
9181 /* Remove all mailers sections which don't have a valid listener.
9182 * This can happen when a mailers section is never referenced.
9183 */
9184 last = &mailers;
9185 while (*last) {
9186 curmailers = *last;
9187 if (curmailers->users) {
9188 last = &curmailers->next;
9189 continue;
9190 }
9191
9192 Warning("Removing incomplete section 'mailers %s'.\n",
9193 curmailers->id);
9194
9195 m = curmailers->mailer_list;
9196 while (m) {
9197 mb = m->next;
9198 free(m->id);
9199 free(m);
9200 m = mb;
9201 }
9202
9203 /* Destroy and unlink this curmailers section.
9204 * Note: curmailers is backed up into *last.
9205 */
9206 free(curmailers->id);
9207 curmailers = curmailers->next;
9208 free(*last);
9209 *last = curmailers;
9210 }
9211 }
9212
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009213 /* Update server_state_file_name to backend name if backend is supposed to use
9214 * a server-state file locally defined and none has been provided */
9215 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9216 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9217 curproxy->server_state_file_name == NULL)
9218 curproxy->server_state_file_name = strdup(curproxy->id);
9219 }
9220
Willy Tarreau34eb6712011-10-24 18:15:04 +02009221 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009222 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009223 MEM_F_SHARED);
9224
Willy Tarreaubb925012009-07-23 13:36:36 +02009225 if (cfgerr > 0)
9226 err_code |= ERR_ALERT | ERR_FATAL;
9227 out:
9228 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009229}
9230
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009231/*
9232 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9233 * parsing sessions.
9234 */
9235void cfg_register_keywords(struct cfg_kw_list *kwl)
9236{
9237 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9238}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009239
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009240/*
9241 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9242 */
9243void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9244{
9245 LIST_DEL(&kwl->list);
9246 LIST_INIT(&kwl->list);
9247}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009248
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009249/* this function register new section in the haproxy configuration file.
9250 * <section_name> is the name of this new section and <section_parser>
9251 * is the called parser. If two section declaration have the same name,
9252 * only the first declared is used.
9253 */
9254int cfg_register_section(char *section_name,
9255 int (*section_parser)(const char *, int, char **, int))
9256{
9257 struct cfg_section *cs;
9258
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009259 list_for_each_entry(cs, &sections, list) {
9260 if (strcmp(cs->section_name, section_name) == 0) {
9261 Alert("register section '%s': already registered.\n", section_name);
9262 return 0;
9263 }
9264 }
9265
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009266 cs = calloc(1, sizeof(*cs));
9267 if (!cs) {
9268 Alert("register section '%s': out of memory.\n", section_name);
9269 return 0;
9270 }
9271
9272 cs->section_name = section_name;
9273 cs->section_parser = section_parser;
9274
9275 LIST_ADDQ(&sections, &cs->list);
9276
9277 return 1;
9278}
9279
Willy Tarreaubaaee002006-06-26 02:48:02 +02009280/*
David Carlier845efb52015-09-25 11:49:18 +01009281 * free all config section entries
9282 */
9283void cfg_unregister_sections(void)
9284{
9285 struct cfg_section *cs, *ics;
9286
9287 list_for_each_entry_safe(cs, ics, &sections, list) {
9288 LIST_DEL(&cs->list);
9289 free(cs);
9290 }
9291}
9292
Christopher Faulet7110b402016-10-26 11:09:44 +02009293void cfg_backup_sections(struct list *backup_sections)
9294{
9295 struct cfg_section *cs, *ics;
9296
9297 list_for_each_entry_safe(cs, ics, &sections, list) {
9298 LIST_DEL(&cs->list);
9299 LIST_ADDQ(backup_sections, &cs->list);
9300 }
9301}
9302
9303void cfg_restore_sections(struct list *backup_sections)
9304{
9305 struct cfg_section *cs, *ics;
9306
9307 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9308 LIST_DEL(&cs->list);
9309 LIST_ADDQ(&sections, &cs->list);
9310 }
9311}
9312
Willy Tarreau659fbf02016-05-26 17:55:28 +02009313__attribute__((constructor))
9314static void cfgparse_init(void)
9315{
9316 /* Register internal sections */
9317 cfg_register_section("listen", cfg_parse_listen);
9318 cfg_register_section("frontend", cfg_parse_listen);
9319 cfg_register_section("backend", cfg_parse_listen);
9320 cfg_register_section("defaults", cfg_parse_listen);
9321 cfg_register_section("global", cfg_parse_global);
9322 cfg_register_section("userlist", cfg_parse_users);
9323 cfg_register_section("peers", cfg_parse_peers);
9324 cfg_register_section("mailers", cfg_parse_mailers);
9325 cfg_register_section("namespace_list", cfg_parse_netns);
9326 cfg_register_section("resolvers", cfg_parse_resolvers);
9327}
9328
David Carlier845efb52015-09-25 11:49:18 +01009329/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009330 * Local variables:
9331 * c-indent-level: 8
9332 * c-basic-offset: 8
9333 * End:
9334 */