blob: b42dd540422bf7bf1e44ed8688c3b92f77a90b4a [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>
Emeric Brunc60def82017-09-27 14:59:38 +020045#include <common/hathreads.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020046
47#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020048#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020049#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010051#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020052#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090053#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020054#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010055#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056
Willy Tarreaueb0c6142007-05-07 00:53:22 +020057#include <proto/acl.h>
Christopher Faulet4fce0d82017-09-18 11:57:31 +020058#include <proto/action.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010059#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020061#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020063#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020064#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010065#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020066#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020067#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020068#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020069#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010070#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020071#include <proto/lb_fwlc.h>
72#include <proto/lb_fwrr.h>
73#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020076#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
William Lallemandd2ff56d2017-10-16 11:06:50 +0200131 int (*post_section_parser)();
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
William Lallemand48b4bb42017-10-23 14:36:34 +0200139/* store post configuration parsing */
140
141struct cfg_postparser {
142 struct list list;
143 char *name;
144 int (*func)();
145};
146
147struct list postparsers = LIST_HEAD_INIT(postparsers);
148
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100151 const char *name;
152 unsigned int val;
153 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100154 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100156};
157
158/* proxy->options */
159static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100160{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
162 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
163 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
165 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
166 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200168 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200169 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100170 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
172 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
173 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100175#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100179#endif
180
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100182};
183
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184/* proxy->options2 */
185static const struct cfg_opt cfg_opts2[] =
186{
187#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
189 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
190 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100191#else
192 { "splice-request", 0, 0, 0, 0 },
193 { "splice-response", 0, 0, 0, 0 },
194 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
197 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
198 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
199 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
200 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
201 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
202 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
203 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
204 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400205 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100206 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200207 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200208 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100209 { NULL, 0, 0, 0 }
210};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau6daf3432008-01-22 16:44:08 +0100212static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
214int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100215int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100216char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200218/* List head of all known configuration keywords */
219static struct cfg_kw_list cfg_keywords = {
220 .list = LIST_HEAD_INIT(cfg_keywords.list)
221};
222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223/*
224 * converts <str> to a list of listeners which are dynamically allocated.
225 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
226 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
227 * - <port> is a numerical port from 1 to 65535 ;
228 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
229 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200230 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
231 * not NULL, it must be a valid pointer to either NULL or a freeable area that
232 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234int 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 +0200235{
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 int port, end;
238
239 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200240
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241 while (next && *next) {
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200242 struct sockaddr_storage *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100243 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
245 str = next;
246 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100247 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248 *next++ = 0;
249 }
250
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100251 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200252 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200253 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100254 if (!ss2)
255 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100257 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100258 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100263 if (!port || !end) {
264 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
265 goto fail;
266 }
267
Emeric Bruned760922010-10-22 17:59:25 +0200268 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200269 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200270 goto fail;
271 }
272
273 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200274 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200275 goto fail;
276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100278 else if (ss2->ss_family == AF_UNSPEC) {
279 socklen_t addr_len;
280
281 /* We want to attach to an already bound fd whose number
282 * is in the addr part of ss2 when cast to sockaddr_in.
283 * Note that by definition there is a single listener.
284 * We still have to determine the address family to
285 * register the correct protocol.
286 */
287 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
288 addr_len = sizeof(*ss2);
289 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
290 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
291 goto fail;
292 }
293
294 port = end = get_host_port(ss2);
295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100297 /* OK the address looks correct */
Willy Tarreau0de59fd2017-09-15 08:10:44 +0200298 if (!create_listeners(bind_conf, ss2, port, end, fd, err)) {
299 memprintf(err, "%s for address '%s'.\n", *err, str);
300 goto fail;
301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
William Lallemand6e62fb62015-04-28 16:55:23 +0200310/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100311 * Report an error in <msg> when there are too many arguments. This version is
312 * intended to be used by keyword parsers so that the message will be included
313 * into the general error message. The index is the current keyword in args.
314 * Return 0 if the number of argument is correct, otherwise build a message and
315 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
316 * message may also be null, it will simply not be produced (useful to check only).
317 * <msg> and <err_code> are only affected on error.
318 */
319int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
320{
321 int i;
322
323 if (!*args[index + maxarg + 1])
324 return 0;
325
326 if (msg) {
327 *msg = NULL;
328 memprintf(msg, "%s", args[0]);
329 for (i = 1; i <= index; i++)
330 memprintf(msg, "%s %s", *msg, args[i]);
331
332 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
333 }
334 if (err_code)
335 *err_code |= ERR_ALERT | ERR_FATAL;
336
337 return 1;
338}
339
340/*
341 * same as too_many_args_idx with a 0 index
342 */
343int too_many_args(int maxarg, char **args, char **msg, int *err_code)
344{
345 return too_many_args_idx(maxarg, 0, args, msg, err_code);
346}
347
348/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200349 * Report a fatal Alert when there is too much arguments
350 * The index is the current keyword in args
351 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
352 * Fill err_code with an ERR_ALERT and an ERR_FATAL
353 */
354int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
355{
356 char *kw = NULL;
357 int i;
358
359 if (!*args[index + maxarg + 1])
360 return 0;
361
362 memprintf(&kw, "%s", args[0]);
363 for (i = 1; i <= index; i++) {
364 memprintf(&kw, "%s %s", kw, args[i]);
365 }
366
367 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
368 free(kw);
369 *err_code |= ERR_ALERT | ERR_FATAL;
370 return 1;
371}
372
373/*
374 * same as alertif_too_many_args_idx with a 0 index
375 */
376int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
377{
378 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
379}
380
Willy Tarreau620408f2016-10-21 16:37:51 +0200381/* Report a warning if a rule is placed after a 'tcp-request session' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
384int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
385{
386 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200394/* Report a warning if a rule is placed after a 'tcp-request content' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
397int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
398{
399 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau61d18892009-03-31 10:49:21 +0200407/* Report a warning if a rule is placed after a 'block' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200412 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200413 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau5002f572014-04-23 01:32:02 +0200420/* Report a warning if a rule is placed after an 'http_request' rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
423int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
424{
425 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
426 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
Willy Tarreau61d18892009-03-31 10:49:21 +0200433/* Report a warning if a rule is placed after a reqrewrite rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100436int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200437{
438 if (proxy->req_exp) {
439 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' 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 reqadd rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100451 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
464 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
472/* Report a warning if a rule is placed after a 'use_backend' rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
Willy Tarreauee445d92014-04-23 01:39:04 +0200485/* Report a warning if a rule is placed after a 'use-server' rule.
486 * Return 1 if the warning has been emitted, otherwise 0.
487 */
488int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
489{
490 if (!LIST_ISEMPTY(&proxy->server_rules)) {
491 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
492 file, line, arg);
493 return 1;
494 }
495 return 0;
496}
497
Willy Tarreaud39ad442016-11-25 15:16:12 +0100498/* report a warning if a redirect rule is dangerously placed */
499int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200500{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100501 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200502 warnif_rule_after_use_server(proxy, file, line, arg);
503}
504
Willy Tarreaud39ad442016-11-25 15:16:12 +0100505/* report a warning if a reqadd rule is dangerously placed */
506int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200507{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100508 return warnif_rule_after_redirect(proxy, file, line, arg) ||
509 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a reqxxx rule is dangerously placed */
513int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
516 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200517}
518
519/* report a warning if an http-request rule is dangerously placed */
520int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
521{
Willy Tarreau61d18892009-03-31 10:49:21 +0200522 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100523 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a block rule is dangerously placed */
527int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_http_req(proxy, file, line, arg) ||
530 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200531}
532
Willy Tarreaud39ad442016-11-25 15:16:12 +0100533/* report a warning if a "tcp request content" rule is dangerously placed */
534int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200535{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 return warnif_rule_after_block(proxy, file, line, arg) ||
537 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a "tcp request session" rule is dangerously placed */
541int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
544 warnif_misplaced_tcp_cont(proxy, file, line, arg);
545}
546
547/* report a warning if a "tcp request connection" rule is dangerously placed */
548int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
549{
550 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
551 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200552}
553
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100554/* Report it if a request ACL condition uses some keywords that are incompatible
555 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
556 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
557 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100558 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100559static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100560{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200562 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100563
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565 return 0;
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567 acl = acl_cond_conflicts(cond, where);
568 if (acl) {
569 if (acl->name && *acl->name)
570 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
571 file, line, acl->name, sample_ckp_names(where));
572 else
573 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 +0200574 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 return ERR_WARN;
576 }
577 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100578 return 0;
579
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 if (acl->name && *acl->name)
581 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200582 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100583 else
584 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200585 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100586 return ERR_WARN;
587}
588
Christopher Faulet62519022017-10-16 15:49:32 +0200589/* Parse a string representing a process number or a set of processes. It must
590 * be "all", "odd", "even" or a number between 1 and <LONGBITS>. It returns a
591 * mask where bits are set for corresponding processes or 0 if an error occured.
592 *
593 * Note: this function can also be used to parse a thread number or a set of
594 * threads.
595 */
596static unsigned long parse_process_number(const char *arg)
597{
598 unsigned long proc = 0;
599
600 if (strcmp(arg, "all") == 0)
601 proc = ~0UL;
602 else if (strcmp(arg, "odd") == 0)
603 proc = ~0UL/3UL; /* 0x555....555 */
604 else if (strcmp(arg, "even") == 0)
605 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
606 else {
607 proc = atol(arg);
608 if (proc >= 1 && proc <= LONGBITS)
609 proc = 1UL << (proc - 1);
610 }
611 return proc;
612}
613
614/* Parse cpu sets. Each CPU set is either a unique number between 0 and
615 * <LONGBITS> or a range with two such numbers delimited by a dash
616 * ('-'). Multiple CPU numbers or ranges may be specified. On success, it
617 * returns 0. otherwise it returns 1 with an error message in <err>.
618 */
619static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
620{
621 int cur_arg = 0;
622
623 *cpu_set = 0;
624 while (*args[cur_arg]) {
625 char *dash;
626 unsigned int low, high;
627
628 if (!isdigit((int)*args[cur_arg])) {
629 memprintf(err, "'%s' is not a CPU range.\n", args[cur_arg]);
630 return -1;
631 }
632
633 low = high = str2uic(args[cur_arg]);
634 if ((dash = strchr(args[cur_arg], '-')) != NULL)
635 high = str2uic(dash + 1);
636
637 if (high < low) {
638 unsigned int swap = low;
639 low = high;
640 high = swap;
641 }
642
643 if (high >= LONGBITS) {
644 memprintf(err, "supports CPU numbers from 0 to %d.\n", LONGBITS - 1);
645 return 1;
646 }
647
648 while (low <= high)
649 *cpu_set |= 1UL << low++;
650
651 cur_arg++;
652 }
653 return 0;
654}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200655/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 * parse a line in a <global> section. Returns the error code, 0 if OK, or
657 * any combination of :
658 * - ERR_ABORT: must abort ASAP
659 * - ERR_FATAL: we can continue parsing but not start the service
660 * - ERR_WARN: a warning has been emitted
661 * - ERR_ALERT: an alert has been emitted
662 * Only the two first ones can stop processing, the two others are just
663 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200665int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666{
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200668 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669
670 if (!strcmp(args[0], "global")) { /* new section */
671 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200672 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200676 if (alertif_too_many_args(0, file, linenum, args, &err_code))
677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 global.mode |= MODE_DAEMON;
679 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200680 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200682 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200683 if (*args[1]) {
684 if (!strcmp(args[1], "exit-on-failure")) {
685 global.tune.options |= GTUNE_EXIT_ONFAILURE;
686 } else {
687 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200692 global.mode |= MODE_MWORKER;
693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200695 if (alertif_too_many_args(0, file, linenum, args, &err_code))
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 global.mode |= MODE_DEBUG;
698 }
699 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200700 if (alertif_too_many_args(0, file, linenum, args, &err_code))
701 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100702 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200704 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200705 if (alertif_too_many_args(0, file, linenum, args, &err_code))
706 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100707 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200710 if (alertif_too_many_args(0, file, linenum, args, &err_code))
711 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100712 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100714 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200715 if (alertif_too_many_args(0, file, linenum, args, &err_code))
716 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100717 global.tune.options &= ~GTUNE_USE_SPLICE;
718 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200719 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200720 if (alertif_too_many_args(0, file, linenum, args, &err_code))
721 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200722 global.tune.options &= ~GTUNE_USE_GAI;
723 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000724 else if (!strcmp(args[0], "noreuseport")) {
725 if (alertif_too_many_args(0, file, linenum, args, &err_code))
726 goto out;
727 global.tune.options &= ~GTUNE_USE_REUSEPORT;
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(0, file, linenum, args, &err_code))
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 global.mode |= MODE_QUIET;
733 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200734 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
736 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200737 if (global.tune.maxpollevents != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200739 err_code |= ERR_ALERT;
740 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200741 }
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200746 }
747 global.tune.maxpollevents = atol(args[1]);
748 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100749 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200750 if (alertif_too_many_args(1, file, linenum, args, &err_code))
751 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100752 if (global.tune.maxaccept != 0) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 err_code |= ERR_ALERT;
755 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100761 }
762 global.tune.maxaccept = atol(args[1]);
763 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200764 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200765 if (alertif_too_many_args(1, file, linenum, args, &err_code))
766 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 global.tune.chksize = atol(args[1]);
773 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100774 else if (!strcmp(args[0], "tune.recv_enough")) {
775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.recv_enough = atol(args[1]);
783 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100784 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200785 if (alertif_too_many_args(1, file, linenum, args, &err_code))
786 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100787 if (*(args[1]) == 0) {
788 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
791 }
792 global.tune.buf_limit = atol(args[1]);
793 if (global.tune.buf_limit) {
794 if (global.tune.buf_limit < 3)
795 global.tune.buf_limit = 3;
796 if (global.tune.buf_limit <= global.tune.reserved_bufs)
797 global.tune.buf_limit = global.tune.reserved_bufs + 1;
798 }
799 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100800 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200801 if (alertif_too_many_args(1, file, linenum, args, &err_code))
802 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808 global.tune.reserved_bufs = atol(args[1]);
809 if (global.tune.reserved_bufs < 2)
810 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100811 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
812 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100813 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200814 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200815 if (alertif_too_many_args(1, file, linenum, args, &err_code))
816 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200817 if (*(args[1]) == 0) {
818 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
819 err_code |= ERR_ALERT | ERR_FATAL;
820 goto out;
821 }
822 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200823 if (global.tune.bufsize <= 0) {
824 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200828 }
829 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200830 if (alertif_too_many_args(1, file, linenum, args, &err_code))
831 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200832 if (*(args[1]) == 0) {
833 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200838 if (global.tune.maxrewrite < 0) {
839 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200843 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100844 else if (!strcmp(args[0], "tune.idletimer")) {
845 unsigned int idle;
846 const char *res;
847
William Lallemand1a748ae2015-05-19 16:37:23 +0200848 if (alertif_too_many_args(1, file, linenum, args, &err_code))
849 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855
856 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
857 if (res) {
858 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
859 file, linenum, *res, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863
864 if (idle > 65535) {
865 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
869 global.tune.idle_timer = idle;
870 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100871 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200872 if (alertif_too_many_args(1, file, linenum, args, &err_code))
873 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100874 if (global.tune.client_rcvbuf != 0) {
875 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT;
877 goto out;
878 }
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 global.tune.client_rcvbuf = atol(args[1]);
885 }
886 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200887 if (alertif_too_many_args(1, file, linenum, args, &err_code))
888 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100889 if (global.tune.server_rcvbuf != 0) {
890 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT;
892 goto out;
893 }
894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.server_rcvbuf = atol(args[1]);
900 }
901 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100904 if (global.tune.client_sndbuf != 0) {
905 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT;
907 goto out;
908 }
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.tune.client_sndbuf = atol(args[1]);
915 }
916 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200917 if (alertif_too_many_args(1, file, linenum, args, &err_code))
918 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100919 if (global.tune.server_sndbuf != 0) {
920 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT;
922 goto out;
923 }
924 if (*(args[1]) == 0) {
925 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 global.tune.server_sndbuf = atol(args[1]);
930 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200931 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200932 if (alertif_too_many_args(1, file, linenum, args, &err_code))
933 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.pipesize = atol(args[1]);
940 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100941 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
948 }
949 global.tune.cookie_len = atol(args[1]) + 1;
950 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200951 else if (!strcmp(args[0], "tune.http.logurilen")) {
952 if (alertif_too_many_args(1, file, linenum, args, &err_code))
953 goto out;
954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 global.tune.requri_len = atol(args[1]) + 1;
960 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200961 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200969 global.tune.max_http_hdr = atoi(args[1]);
970 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
971 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
972 file, linenum, args[0]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200976 }
William Lallemandf3747832012-11-09 12:33:10 +0100977 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200978 if (alertif_too_many_args(1, file, linenum, args, &err_code))
979 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100980 if (*args[1]) {
981 global.tune.comp_maxlevel = atoi(args[1]);
982 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
983 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
984 file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 } else {
989 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
990 file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200995 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
996 if (*args[1]) {
997 global.tune.pattern_cache = atoi(args[1]);
998 if (global.tune.pattern_cache < 0) {
999 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1000 file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 } else {
1005 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1006 file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009 }
1010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001012 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001015 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT;
1017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001018 }
1019 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 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001024 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1025 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]);
1026 err_code |= ERR_WARN;
1027 goto out;
1028 }
1029
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 }
1031 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001035 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001036 err_code |= ERR_ALERT;
1037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 }
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001044 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1045 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]);
1046 err_code |= ERR_WARN;
1047 goto out;
1048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
Simon Horman98637e52014-06-20 12:30:16 +09001050 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001051 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1052 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001053 global.external_check = 1;
1054 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001055 /* user/group name handling */
1056 else if (!strcmp(args[0], "user")) {
1057 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001058 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1059 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001060 if (global.uid != 0) {
1061 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001062 err_code |= ERR_ALERT;
1063 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001064 }
1065 errno = 0;
1066 ha_user = getpwnam(args[1]);
1067 if (ha_user != NULL) {
1068 global.uid = (int)ha_user->pw_uid;
1069 }
1070 else {
1071 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 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001073 }
1074 }
1075 else if (!strcmp(args[0], "group")) {
1076 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1078 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001079 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001080 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001081 err_code |= ERR_ALERT;
1082 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001083 }
1084 errno = 0;
1085 ha_group = getgrnam(args[1]);
1086 if (ha_group != NULL) {
1087 global.gid = (int)ha_group->gr_gid;
1088 }
1089 else {
1090 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 +02001091 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001092 }
1093 }
1094 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001096 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 }
1103 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001104 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1105 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1106 file, linenum, args[0], LONGBITS, global.nbproc);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
1109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
Christopher Fauletbe0faa22017-08-29 15:37:10 +02001111 else if (!strcmp(args[0], "nbthread")) {
1112 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1113 goto out;
1114 if (*(args[1]) == 0) {
1115 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto out;
1118 }
1119 global.nbthread = atol(args[1]);
1120 if (global.nbthread < 1 || global.nbthread > LONGBITS) {
1121 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1122 file, linenum, args[0], LONGBITS, global.nbthread);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
1125 }
1126#ifndef USE_THREAD
1127 if (global.nbthread > 1) {
1128 Alert("HAProxy is not compiled with threads support, please check build options for USE_THREAD.\n");
1129 global.nbthread = 1;
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
1132 }
1133#endif
1134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001136 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 if (global.maxconn != 0) {
1139 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT;
1141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142 }
1143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
1148 global.maxconn = atol(args[1]);
1149#ifdef SYSTEM_MAXCONN
1150 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1151 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);
1152 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001153 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155#endif /* SYSTEM_MAXCONN */
1156 }
Emeric Brun850efd52014-01-29 12:24:34 +01001157 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001158 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1159 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001160 if (*(args[1]) == 0) {
1161 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
1165 if (strcmp(args[1],"none") == 0)
1166 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1167 else if (strcmp(args[1],"required") == 0)
1168 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1169 else {
1170 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
1173 }
1174 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001175 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001176 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1177 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001178 if (global.cps_lim != 0) {
1179 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1180 err_code |= ERR_ALERT;
1181 goto out;
1182 }
1183 if (*(args[1]) == 0) {
1184 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
1187 }
1188 global.cps_lim = atol(args[1]);
1189 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001190 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001191 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1192 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001193 if (global.sps_lim != 0) {
1194 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT;
1196 goto out;
1197 }
1198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203 global.sps_lim = atol(args[1]);
1204 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001205 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001206 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1207 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001208 if (global.ssl_lim != 0) {
1209 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1210 err_code |= ERR_ALERT;
1211 goto out;
1212 }
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218 global.ssl_lim = atol(args[1]);
1219 }
William Lallemandd85f9172012-11-09 17:05:39 +01001220 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001221 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1222 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001223 if (*(args[1]) == 0) {
1224 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228 global.comp_rate_lim = atoi(args[1]) * 1024;
1229 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001230 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001231 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1232 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001233 if (global.maxpipes != 0) {
1234 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001235 err_code |= ERR_ALERT;
1236 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001237 }
1238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001242 }
1243 global.maxpipes = atol(args[1]);
1244 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001245 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001246 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1247 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001248 if (*(args[1]) == 0) {
1249 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
William Lallemande3a7d992012-11-20 11:25:20 +01001253 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001254 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001255 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001256 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1257 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001258 if (*(args[1]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001264 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001265 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001269 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001270
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (global.rlimit_nofile != 0) {
1275 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001276 err_code |= ERR_ALERT;
1277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 }
1279 if (*(args[1]) == 0) {
1280 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 }
1284 global.rlimit_nofile = atol(args[1]);
1285 }
1286 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 if (global.chroot != NULL) {
1290 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_ALERT;
1292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 }
1294 if (*(args[1]) == 0) {
1295 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001298 }
1299 global.chroot = strdup(args[1]);
1300 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001301 else if (!strcmp(args[0], "description")) {
1302 int i, len=0;
1303 char *d;
1304
1305 if (!*args[1]) {
1306 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1307 file, linenum, args[0]);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
Willy Tarreau348acfe2014-04-14 15:00:39 +02001312 for (i = 1; *args[i]; i++)
1313 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001314
1315 if (global.desc)
1316 free(global.desc);
1317
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001318 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001319
Willy Tarreau348acfe2014-04-14 15:00:39 +02001320 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1321 for (i = 2; *args[i]; i++)
1322 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001323 }
1324 else if (!strcmp(args[0], "node")) {
1325 int i;
1326 char c;
1327
William Lallemand1a748ae2015-05-19 16:37:23 +02001328 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1329 goto out;
1330
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001331 for (i=0; args[1][i]; i++) {
1332 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001333 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1334 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001335 break;
1336 }
1337
1338 if (!i || args[1][i]) {
1339 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1340 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1341 file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345
1346 if (global.node)
1347 free(global.node);
1348
1349 global.node = strdup(args[1]);
1350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 if (global.pidfile != NULL) {
1355 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 if (*(args[1]) == 0) {
1360 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 }
1364 global.pidfile = strdup(args[1]);
1365 }
Emeric Bruned760922010-10-22 17:59:25 +02001366 else if (!strcmp(args[0], "unix-bind")) {
1367 int cur_arg = 1;
1368 while (*(args[cur_arg])) {
1369 if (!strcmp(args[cur_arg], "prefix")) {
1370 if (global.unix_bind.prefix != NULL) {
1371 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1372 err_code |= ERR_ALERT;
1373 cur_arg += 2;
1374 continue;
1375 }
1376
1377 if (*(args[cur_arg+1]) == 0) {
1378 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
1382 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1383 cur_arg += 2;
1384 continue;
1385 }
1386
1387 if (!strcmp(args[cur_arg], "mode")) {
1388
1389 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1390 cur_arg += 2;
1391 continue;
1392 }
1393
1394 if (!strcmp(args[cur_arg], "uid")) {
1395
1396 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1397 cur_arg += 2;
1398 continue;
1399 }
1400
1401 if (!strcmp(args[cur_arg], "gid")) {
1402
1403 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1404 cur_arg += 2;
1405 continue;
1406 }
1407
1408 if (!strcmp(args[cur_arg], "user")) {
1409 struct passwd *user;
1410
1411 user = getpwnam(args[cur_arg + 1]);
1412 if (!user) {
1413 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1414 file, linenum, args[0], args[cur_arg + 1 ]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418
1419 global.unix_bind.ux.uid = user->pw_uid;
1420 cur_arg += 2;
1421 continue;
1422 }
1423
1424 if (!strcmp(args[cur_arg], "group")) {
1425 struct group *group;
1426
1427 group = getgrnam(args[cur_arg + 1]);
1428 if (!group) {
1429 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1430 file, linenum, args[0], args[cur_arg + 1 ]);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433 }
1434
1435 global.unix_bind.ux.gid = group->gr_gid;
1436 cur_arg += 2;
1437 continue;
1438 }
1439
Willy Tarreaub48f9582011-09-05 01:17:06 +02001440 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001441 file, linenum, args[0]);
1442 err_code |= ERR_ALERT | ERR_FATAL;
1443 goto out;
1444 }
1445 }
William Lallemand0f99e342011-10-12 17:50:54 +02001446 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1447 /* delete previous herited or defined syslog servers */
1448 struct logsrv *back;
1449 struct logsrv *tmp;
1450
1451 if (*(args[1]) != 0) {
1452 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455 }
1456
1457 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1458 LIST_DEL(&tmp->list);
1459 free(tmp);
1460 }
1461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001463 struct sockaddr_storage *sk;
1464 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001465 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001466 int arg = 0;
1467 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001468
William Lallemand1a748ae2015-05-19 16:37:23 +02001469 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1470 goto out;
1471
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 if (*(args[1]) == 0 || *(args[2]) == 0) {
1473 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 }
William Lallemand0f99e342011-10-12 17:50:54 +02001477
Vincent Bernat02779b62016-04-03 13:48:43 +02001478 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001479
Willy Tarreau18324f52014-06-27 18:10:07 +02001480 /* just after the address, a length may be specified */
1481 if (strcmp(args[arg+2], "len") == 0) {
1482 len = atoi(args[arg+3]);
1483 if (len < 80 || len > 65535) {
1484 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1485 file, linenum, args[arg+3]);
1486 err_code |= ERR_ALERT | ERR_FATAL;
1487 goto out;
1488 }
1489 logsrv->maxlen = len;
1490
1491 /* skip these two args */
1492 arg += 2;
1493 }
1494 else
1495 logsrv->maxlen = MAX_SYSLOG_LEN;
1496
Christopher Faulet084aa962017-08-29 16:54:41 +02001497 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02001498 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02001499
Dragan Dosen1322d092015-09-22 16:05:32 +02001500 /* after the length, a format may be specified */
1501 if (strcmp(args[arg+2], "format") == 0) {
1502 logsrv->format = get_log_format(args[arg+3]);
1503 if (logsrv->format < 0) {
1504 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1505 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001506 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001507 goto out;
1508 }
1509
1510 /* skip these two args */
1511 arg += 2;
1512 }
1513
David Carlier97880bb2016-04-08 10:35:26 +01001514 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1515 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001516 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001517 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001518
Willy Tarreau18324f52014-06-27 18:10:07 +02001519 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001520 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001521 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001522 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001523 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 }
1525
William Lallemand0f99e342011-10-12 17:50:54 +02001526 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001527 if (*(args[arg+3])) {
1528 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001529 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001530 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001531 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001532 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 }
1534 }
1535
William Lallemand0f99e342011-10-12 17:50:54 +02001536 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001537 if (*(args[arg+4])) {
1538 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001539 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001540 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001541 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001542 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001543 }
1544 }
1545
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001546 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001547 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001548 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001549 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001550 free(logsrv);
1551 goto out;
1552 }
1553 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001554
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001555 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001556 if (port1 != port2) {
1557 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1558 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001559 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001560 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001561 goto out;
1562 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001563
William Lallemand0f99e342011-10-12 17:50:54 +02001564 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001565 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001566 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568
William Lallemand0f99e342011-10-12 17:50:54 +02001569 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001570 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001571 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1572 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001573
1574 if (global.log_send_hostname != NULL) {
1575 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1576 err_code |= ERR_ALERT;
1577 goto out;
1578 }
1579
1580 if (*(args[1]))
1581 name = args[1];
1582 else
1583 name = hostname;
1584
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001585 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001586 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001587 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001588 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1589 if (global.server_state_base != NULL) {
1590 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1591 err_code |= ERR_ALERT;
1592 goto out;
1593 }
1594
1595 if (!*(args[1])) {
1596 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1597 err_code |= ERR_FATAL;
1598 goto out;
1599 }
1600
1601 global.server_state_base = strdup(args[1]);
1602 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001603 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1604 if (global.server_state_file != NULL) {
1605 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1606 err_code |= ERR_ALERT;
1607 goto out;
1608 }
1609
1610 if (!*(args[1])) {
1611 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1612 err_code |= ERR_FATAL;
1613 goto out;
1614 }
1615
1616 global.server_state_file = strdup(args[1]);
1617 }
Kevinm48936af2010-12-22 16:08:21 +00001618 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001619 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1620 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001621 if (*(args[1]) == 0) {
1622 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001626 chunk_destroy(&global.log_tag);
1627 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001628 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001629 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001630 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1631 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001632 if (global.spread_checks != 0) {
1633 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001634 err_code |= ERR_ALERT;
1635 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001636 }
1637 if (*(args[1]) == 0) {
1638 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
1640 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001641 }
1642 global.spread_checks = atol(args[1]);
1643 if (global.spread_checks < 0 || global.spread_checks > 50) {
1644 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001648 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1649 const char *err;
1650 unsigned int val;
1651
William Lallemand1a748ae2015-05-19 16:37:23 +02001652 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1653 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001654 if (*(args[1]) == 0) {
1655 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
1658 }
1659
1660 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1661 if (err) {
1662 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 }
1665 global.max_spread_checks = val;
1666 if (global.max_spread_checks < 0) {
1667 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1668 err_code |= ERR_ALERT | ERR_FATAL;
1669 }
1670 }
Christopher Faulet62519022017-10-16 15:49:32 +02001671 else if (strcmp(args[0], "cpu-map") == 0) {
1672 /* map a process list to a CPU set */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001673#ifdef USE_CPU_AFFINITY
Christopher Faulet62519022017-10-16 15:49:32 +02001674 unsigned long proc, cpus;
1675 int i;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001676
Christopher Faulet62519022017-10-16 15:49:32 +02001677 proc = parse_process_number(args[1]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001678 if (!proc || !*args[2]) {
Christopher Faulet62519022017-10-16 15:49:32 +02001679 Alert("parsing [%s:%d]: %s expects a process number "
1680 " ('all', 'odd', 'even', or a number from 1 to %d), "
1681 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001682 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
Christopher Faulet62519022017-10-16 15:49:32 +02001686 if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
1687 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001690 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001691 for (i = 0; i < LONGBITS; i++)
1692 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001693 global.cpu_map[i] = cpus;
1694#else
Christopher Faulet62519022017-10-16 15:49:32 +02001695 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1696 file, linenum, args[0]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Christopher Faulet62519022017-10-16 15:49:32 +02001699#endif /* ! USE_CPU_AFFINITY */
1700 }
1701 else if (strcmp(args[0], "thread-map") == 0) {
1702 /* map a thread list to a CPU set */
1703#ifdef USE_CPU_AFFINITY
1704#ifdef USE_THREAD
1705 unsigned long proc, thread, cpus;
1706 int i, j;
1707
1708 proc = parse_process_number(args[1]);
1709 thread = parse_process_number(args[2]);
1710 if (!proc || !thread || !*args[3]) {
1711 Alert("parsing [%s:%d]: %s expects a process number "
1712 "('all', 'odd', 'even', or a number from 1 to %d), "
1713 " followed by a thread number using the same format, "
1714 " followed by a list of CPU ranges with numbers from 0 to %d.\n",
1715 file, linenum, args[0], LONGBITS, LONGBITS - 1);
1716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
1718 }
1719 if (parse_cpu_set((const char **)args+3, &cpus, &errmsg)) {
1720 Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724 for (i = 0; i < LONGBITS; i++)
1725 if (proc & (1UL << i)) {
1726 for (j = 0; j < LONGBITS; j++)
1727 if (thread & (1UL << j))
1728 global.thread_map[i][j] = cpus;
1729 }
1730#else
1731 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_THREAD.\n",
1732 file, linenum, args[0]);
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735#endif /* ! USE_THREAD*/
1736#else
1737 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
1738 file, linenum, args[0]);
1739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
1741#endif /* ! USE_CPU_AFFINITY */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001742 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001743 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1744 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1745 goto out;
1746
1747 if (*(args[2]) == 0) {
1748 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
1751 }
1752
1753 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1754 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1755 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759 }
1760 else if (!strcmp(args[0], "unsetenv")) {
1761 int arg;
1762
1763 if (*(args[1]) == 0) {
1764 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767 }
1768
1769 for (arg = 1; *args[arg]; arg++) {
1770 if (unsetenv(args[arg]) != 0) {
1771 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775 }
1776 }
1777 else if (!strcmp(args[0], "resetenv")) {
1778 extern char **environ;
1779 char **env = environ;
1780
1781 /* args contain variable names to keep, one per argument */
1782 while (*env) {
1783 int arg;
1784
1785 /* look for current variable in among all those we want to keep */
1786 for (arg = 1; *args[arg]; arg++) {
1787 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1788 (*env)[strlen(args[arg])] == '=')
1789 break;
1790 }
1791
1792 /* delete this variable */
1793 if (!*args[arg]) {
1794 char *delim = strchr(*env, '=');
1795
1796 if (!delim || delim - *env >= trash.size) {
1797 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801
1802 memcpy(trash.str, *env, delim - *env);
1803 trash.str[delim - *env] = 0;
1804
1805 if (unsetenv(trash.str) != 0) {
1806 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810 }
1811 else
1812 env++;
1813 }
1814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001816 struct cfg_kw_list *kwl;
1817 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001818 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001819
1820 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1821 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1822 if (kwl->kw[index].section != CFG_GLOBAL)
1823 continue;
1824 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001825 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001826 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001827 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001828 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001829 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001830 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001831 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001832 err_code |= ERR_WARN;
1833 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001834 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001835 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001836 }
1837 }
1838 }
1839
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001841 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001843
Willy Tarreau058e9072009-07-20 09:30:05 +02001844 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001845 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847}
1848
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001849void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001851 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 defproxy.mode = PR_MODE_TCP;
1853 defproxy.state = PR_STNEW;
1854 defproxy.maxconn = cfg_maxpconn;
1855 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001856 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001857 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001858
Simon Horman66183002013-02-23 10:16:43 +09001859 defproxy.defsrv.check.inter = DEF_CHKINTR;
1860 defproxy.defsrv.check.fastinter = 0;
1861 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001862 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1863 defproxy.defsrv.agent.fastinter = 0;
1864 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001865 defproxy.defsrv.check.rise = DEF_RISETIME;
1866 defproxy.defsrv.check.fall = DEF_FALLTIME;
1867 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1868 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001869 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001870 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001871 defproxy.defsrv.maxqueue = 0;
1872 defproxy.defsrv.minconn = 0;
1873 defproxy.defsrv.maxconn = 0;
1874 defproxy.defsrv.slowstart = 0;
1875 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1876 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1877 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001878
1879 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001880 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881}
1882
Willy Tarreauade5ec42010-01-28 19:33:49 +01001883
Willy Tarreau63af98d2014-05-18 08:11:41 +02001884/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1885 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1886 * ERR_FATAL in case of error.
1887 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001888static int create_cond_regex_rule(const char *file, int line,
1889 struct proxy *px, int dir, int action, int flags,
1890 const char *cmd, const char *reg, const char *repl,
1891 const char **cond_start)
1892{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001893 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001894 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001896 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001897 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001898 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 int cs;
1900 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001901
1902 if (px == &defproxy) {
1903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001904 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001905 goto err;
1906 }
1907
1908 if (*reg == 0) {
1909 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001910 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001911 goto err;
1912 }
1913
Christopher Faulet898566e2016-10-26 11:06:28 +02001914 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001915 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001916
Willy Tarreau5321c422010-01-28 20:35:13 +01001917 if (cond_start &&
1918 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02001919 if ((cond = build_acl_cond(file, line, &px->acl, px, cond_start, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001920 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1921 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001922 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001923 goto err;
1924 }
1925 }
1926 else if (cond_start && **cond_start) {
1927 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1928 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001929 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001930 goto err;
1931 }
1932
Willy Tarreau63af98d2014-05-18 08:11:41 +02001933 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001934 (dir == SMP_OPT_DIR_REQ) ?
1935 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1936 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1937 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001938
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001939 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001940 if (!preg) {
1941 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001942 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001943 goto err;
1944 }
1945
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001946 cs = !(flags & REG_ICASE);
1947 cap = !(flags & REG_NOSUB);
1948 error = NULL;
1949 if (!regex_comp(reg, preg, cs, cap, &error)) {
1950 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1951 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001952 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953 goto err;
1954 }
1955
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001956 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001957 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001958 if (repl && err) {
1959 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1960 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001961 ret_code |= ERR_ALERT | ERR_FATAL;
1962 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001963 }
1964
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001965 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001966 ret_code |= ERR_WARN;
1967
1968 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001969
Willy Tarreau63af98d2014-05-18 08:11:41 +02001970 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001971 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001972 err:
1973 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001974 free(errmsg);
1975 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001976}
1977
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978/*
William Lallemand51097192015-04-14 16:35:22 +02001979 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001980 * Returns the error code, 0 if OK, or any combination of :
1981 * - ERR_ABORT: must abort ASAP
1982 * - ERR_FATAL: we can continue parsing but not start the service
1983 * - ERR_WARN: a warning has been emitted
1984 * - ERR_ALERT: an alert has been emitted
1985 * Only the two first ones can stop processing, the two others are just
1986 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001988int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1989{
1990 static struct peers *curpeers = NULL;
1991 struct peer *newpeer = NULL;
1992 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001993 struct bind_conf *bind_conf;
1994 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001995 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001996 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001997
1998 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001999 if (!*args[1]) {
2000 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002001 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002002 goto out;
2003 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002004
William Lallemand6e62fb62015-04-28 16:55:23 +02002005 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2006 goto out;
2007
Emeric Brun32da3c42010-09-23 18:39:19 +02002008 err = invalid_char(args[1]);
2009 if (err) {
2010 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2011 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002012 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002013 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 }
2015
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002016 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002017 /*
2018 * If there are two proxies with the same name only following
2019 * combinations are allowed:
2020 */
2021 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002022 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 +02002023 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 }
2026 }
2027
Vincent Bernat02779b62016-04-03 13:48:43 +02002028 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002029 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2030 err_code |= ERR_ALERT | ERR_ABORT;
2031 goto out;
2032 }
2033
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002034 curpeers->next = cfg_peers;
2035 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002036 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002037 curpeers->conf.line = linenum;
2038 curpeers->last_change = now.tv_sec;
2039 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002040 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002041 }
2042 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002043 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002044 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002045 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002046
2047 if (!*args[2]) {
2048 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2049 file, linenum, args[0]);
2050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
2052 }
2053
2054 err = invalid_char(args[1]);
2055 if (err) {
2056 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2057 file, linenum, *err, args[1]);
2058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
2060 }
2061
Vincent Bernat02779b62016-04-03 13:48:43 +02002062 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002063 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2064 err_code |= ERR_ALERT | ERR_ABORT;
2065 goto out;
2066 }
2067
2068 /* the peers are linked backwards first */
2069 curpeers->count++;
2070 newpeer->next = curpeers->remote;
2071 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002072 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 newpeer->conf.line = linenum;
2074
2075 newpeer->last_change = now.tv_sec;
2076 newpeer->id = strdup(args[1]);
2077
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002078 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002079 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002080 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002083 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002084
2085 proto = protocol_by_family(sk->ss_family);
2086 if (!proto || !proto->connect) {
2087 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2088 file, linenum, args[0], args[1]);
2089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002092
2093 if (port1 != port2) {
2094 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2095 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
2099
Willy Tarreau2aa38802013-02-20 19:20:59 +01002100 if (!port1) {
2101 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2102 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
2105 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002106
Emeric Brun32da3c42010-09-23 18:39:19 +02002107 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002108 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002109 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002110 newpeer->sock_init_arg = NULL;
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002111 HA_SPIN_INIT(&newpeer->lock);
Willy Tarreau26d8c592012-05-07 18:12:14 +02002112
Emeric Brun32da3c42010-09-23 18:39:19 +02002113 if (strcmp(newpeer->id, localpeer) == 0) {
2114 /* Current is local peer, it define a frontend */
2115 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002116 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002117
2118 if (!curpeers->peers_fe) {
2119 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2120 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124
Willy Tarreau237250c2011-07-29 01:49:03 +02002125 init_new_proxy(curpeers->peers_fe);
2126 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002127 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002128 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2129 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002130 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002132 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002133
Willy Tarreau902636f2013-03-10 19:44:48 +01002134 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2135 if (errmsg && *errmsg) {
2136 indent_msg(&errmsg, 2);
2137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002138 }
2139 else
2140 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2141 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 err_code |= ERR_FATAL;
2143 goto out;
2144 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145
2146 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002147 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002148 l->maxconn = curpeers->peers_fe->maxconn;
2149 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002150 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002151 l->analysers |= curpeers->peers_fe->fe_req_ana;
2152 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002153 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2154 global.maxsock += l->maxconn;
2155 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002156 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002157 else {
2158 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2159 file, linenum, args[0], args[1],
2160 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2161 err_code |= ERR_FATAL;
2162 goto out;
2163 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002164 }
2165 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002166 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2167 curpeers->state = PR_STSTOPPED;
2168 }
2169 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2170 curpeers->state = PR_STNEW;
2171 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002172 else if (*args[0] != 0) {
2173 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177
2178out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002179 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002180 return err_code;
2181}
2182
Baptiste Assmann325137d2015-04-13 23:40:55 +02002183/*
2184 * Parse a <resolvers> section.
2185 * Returns the error code, 0 if OK, or any combination of :
2186 * - ERR_ABORT: must abort ASAP
2187 * - ERR_FATAL: we can continue parsing but not start the service
2188 * - ERR_WARN: a warning has been emitted
2189 * - ERR_ALERT: an alert has been emitted
2190 * Only the two first ones can stop processing, the two others are just
2191 * indicators.
2192 */
2193int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2194{
2195 static struct dns_resolvers *curr_resolvers = NULL;
2196 struct dns_nameserver *newnameserver = NULL;
2197 const char *err;
2198 int err_code = 0;
2199 char *errmsg = NULL;
2200
2201 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2202 if (!*args[1]) {
2203 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2204 err_code |= ERR_ALERT | ERR_ABORT;
2205 goto out;
2206 }
2207
2208 err = invalid_char(args[1]);
2209 if (err) {
2210 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2211 file, linenum, *err, args[0], args[1]);
2212 err_code |= ERR_ALERT | ERR_ABORT;
2213 goto out;
2214 }
2215
2216 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2217 /* Error if two resolvers owns the same name */
2218 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2219 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2220 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2221 err_code |= ERR_ALERT | ERR_ABORT;
2222 }
2223 }
2224
Vincent Bernat02779b62016-04-03 13:48:43 +02002225 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2227 err_code |= ERR_ALERT | ERR_ABORT;
2228 goto out;
2229 }
2230
2231 /* default values */
2232 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2233 curr_resolvers->conf.file = strdup(file);
2234 curr_resolvers->conf.line = linenum;
2235 curr_resolvers->id = strdup(args[1]);
2236 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002237 /* default maximum response size */
2238 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002239 /* default hold period for nx, other, refuse and timeout is 30s */
2240 curr_resolvers->hold.nx = 30000;
2241 curr_resolvers->hold.other = 30000;
2242 curr_resolvers->hold.refused = 30000;
2243 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002244 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002245 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002246 curr_resolvers->hold.valid = 10000;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002247 curr_resolvers->timeout.resolve = 1000;
2248 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002249 curr_resolvers->resolve_retries = 3;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002250 curr_resolvers->nb_nameservers = 0;
2251 LIST_INIT(&curr_resolvers->nameservers);
2252 LIST_INIT(&curr_resolvers->resolutions.curr);
2253 LIST_INIT(&curr_resolvers->resolutions.wait);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002254 HA_SPIN_INIT(&curr_resolvers->lock);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002255 }
2256 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2257 struct sockaddr_storage *sk;
2258 int port1, port2;
2259 struct protocol *proto;
2260
2261 if (!*args[2]) {
2262 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2263 file, linenum, args[0]);
2264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
2266 }
2267
2268 err = invalid_char(args[1]);
2269 if (err) {
2270 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2271 file, linenum, *err, args[1]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
2275
Christopher Faulet67957bd2017-09-27 11:00:59 +02002276 list_for_each_entry(newnameserver, &curr_resolvers->nameservers, list) {
Baptiste Assmanna315c552015-11-02 22:55:49 +01002277 /* Error if two resolvers owns the same name */
2278 if (strcmp(newnameserver->id, args[1]) == 0) {
2279 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2280 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 }
2283 }
2284
Vincent Bernat02779b62016-04-03 13:48:43 +02002285 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2287 err_code |= ERR_ALERT | ERR_ABORT;
2288 goto out;
2289 }
2290
2291 /* the nameservers are linked backward first */
Christopher Faulet67957bd2017-09-27 11:00:59 +02002292 LIST_ADDQ(&curr_resolvers->nameservers, &newnameserver->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002293 newnameserver->resolvers = curr_resolvers;
2294 newnameserver->conf.file = strdup(file);
2295 newnameserver->conf.line = linenum;
2296 newnameserver->id = strdup(args[1]);
2297
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002298 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002299 if (!sk) {
2300 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
2304
2305 proto = protocol_by_family(sk->ss_family);
2306 if (!proto || !proto->connect) {
2307 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2308 file, linenum, args[0], args[1]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 if (port1 != port2) {
2314 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2315 file, linenum, args[0], args[1], args[2]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002320 if (!port1 && !port2) {
2321 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2322 file, linenum, args[0], args[1]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326
Baptiste Assmann325137d2015-04-13 23:40:55 +02002327 newnameserver->addr = *sk;
2328 }
2329 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2330 const char *res;
2331 unsigned int time;
2332
2333 if (!*args[2]) {
2334 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2335 file, linenum, args[0]);
2336 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2341 if (res) {
2342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2343 file, linenum, *res, args[0]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002347 if (strcmp(args[1], "nx") == 0)
2348 curr_resolvers->hold.nx = time;
2349 else if (strcmp(args[1], "other") == 0)
2350 curr_resolvers->hold.other = time;
2351 else if (strcmp(args[1], "refused") == 0)
2352 curr_resolvers->hold.refused = time;
2353 else if (strcmp(args[1], "timeout") == 0)
2354 curr_resolvers->hold.timeout = time;
2355 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002356 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002357 else if (strcmp(args[1], "obsolete") == 0)
2358 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002359 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002360 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002361 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
2366 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002367 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002368 int i = 0;
2369
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002370 if (!*args[1]) {
2371 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2372 file, linenum, args[0]);
2373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
2375 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002376
2377 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002378 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2379 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2380 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
2384
2385 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002386 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002387 else if (strcmp(args[0], "resolution_pool_size") == 0) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002388 Warning("parsing [%s:%d] : '%s' directive is now deprecated and ignored.\n",
2389 file, linenum, args[0]);
2390 err_code |= ERR_WARN;
2391 goto out;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002392 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002393 else if (strcmp(args[0], "resolve_retries") == 0) {
2394 if (!*args[1]) {
2395 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2396 file, linenum, args[0]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400 curr_resolvers->resolve_retries = atoi(args[1]);
2401 }
2402 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002403 if (!*args[1]) {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002404 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments.\n",
Baptiste Assmann325137d2015-04-13 23:40:55 +02002405 file, linenum, args[0]);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
2408 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002409 else if (strcmp(args[1], "retry") == 0 ||
2410 strcmp(args[1], "resolve") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002411 const char *res;
Christopher Faulet67957bd2017-09-27 11:00:59 +02002412 unsigned int tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002413
2414 if (!*args[2]) {
2415 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2416 file, linenum, args[0], args[1]);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002420 res = parse_time_err(args[2], &tout, TIME_UNIT_MS);
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002421 if (res) {
2422 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2423 file, linenum, *res, args[0], args[1]);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
2426 }
Christopher Faulet67957bd2017-09-27 11:00:59 +02002427 if (args[1][2] == 't')
2428 curr_resolvers->timeout.retry = tout;
2429 else
2430 curr_resolvers->timeout.resolve = tout;
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002431 }
2432 else {
Christopher Faulet67957bd2017-09-27 11:00:59 +02002433 Alert("parsing [%s:%d] : '%s' expects 'retry' or 'resolve' and <time> as arguments got '%s'.\n",
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002434 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002438 } /* neither "nameserver" nor "resolvers" */
2439 else if (*args[0] != 0) {
2440 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
2445 out:
2446 free(errmsg);
2447 return err_code;
2448}
Simon Horman0d16a402015-01-30 11:22:58 +09002449
2450/*
William Lallemand51097192015-04-14 16:35:22 +02002451 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002452 * Returns the error code, 0 if OK, or any combination of :
2453 * - ERR_ABORT: must abort ASAP
2454 * - ERR_FATAL: we can continue parsing but not start the service
2455 * - ERR_WARN: a warning has been emitted
2456 * - ERR_ALERT: an alert has been emitted
2457 * Only the two first ones can stop processing, the two others are just
2458 * indicators.
2459 */
2460int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2461{
2462 static struct mailers *curmailers = NULL;
2463 struct mailer *newmailer = NULL;
2464 const char *err;
2465 int err_code = 0;
2466 char *errmsg = NULL;
2467
2468 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2469 if (!*args[1]) {
2470 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2471 err_code |= ERR_ALERT | ERR_ABORT;
2472 goto out;
2473 }
2474
2475 err = invalid_char(args[1]);
2476 if (err) {
2477 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2478 file, linenum, *err, args[0], args[1]);
2479 err_code |= ERR_ALERT | ERR_ABORT;
2480 goto out;
2481 }
2482
2483 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2484 /*
2485 * If there are two proxies with the same name only following
2486 * combinations are allowed:
2487 */
2488 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002489 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 +09002490 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002492 }
2493 }
2494
Vincent Bernat02779b62016-04-03 13:48:43 +02002495 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2497 err_code |= ERR_ALERT | ERR_ABORT;
2498 goto out;
2499 }
2500
2501 curmailers->next = mailers;
2502 mailers = curmailers;
2503 curmailers->conf.file = strdup(file);
2504 curmailers->conf.line = linenum;
2505 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002506 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2507 * But need enough time so that timeouts don't occur
2508 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002509 }
2510 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2511 struct sockaddr_storage *sk;
2512 int port1, port2;
2513 struct protocol *proto;
2514
2515 if (!*args[2]) {
2516 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2517 file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
2522 err = invalid_char(args[1]);
2523 if (err) {
2524 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2525 file, linenum, *err, args[1]);
2526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
2528 }
2529
Vincent Bernat02779b62016-04-03 13:48:43 +02002530 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002531 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2532 err_code |= ERR_ALERT | ERR_ABORT;
2533 goto out;
2534 }
2535
2536 /* the mailers are linked backwards first */
2537 curmailers->count++;
2538 newmailer->next = curmailers->mailer_list;
2539 curmailers->mailer_list = newmailer;
2540 newmailer->mailers = curmailers;
2541 newmailer->conf.file = strdup(file);
2542 newmailer->conf.line = linenum;
2543
2544 newmailer->id = strdup(args[1]);
2545
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002546 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002547 if (!sk) {
2548 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
2552
2553 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002554 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2555 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002556 file, linenum, args[0], args[1]);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
2559 }
2560
2561 if (port1 != port2) {
2562 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2563 file, linenum, args[0], args[1], args[2]);
2564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
2566 }
2567
2568 if (!port1) {
2569 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2570 file, linenum, args[0], args[1], args[2]);
2571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
2573 }
2574
2575 newmailer->addr = *sk;
2576 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002577 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002578 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002579 }
2580 else if (strcmp(args[0], "timeout") == 0) {
2581 if (!*args[1]) {
2582 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2583 file, linenum, args[0]);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587 else if (strcmp(args[1], "mail") == 0) {
2588 const char *res;
2589 unsigned int timeout_mail;
2590 if (!*args[2]) {
2591 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2592 file, linenum, args[0], args[1]);
2593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
2595 }
2596 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2597 if (res) {
2598 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2599 file, linenum, *res, args[0]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
2603 if (timeout_mail <= 0) {
2604 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
2607 }
2608 curmailers->timeout.mail = timeout_mail;
2609 } else {
2610 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2611 file, linenum, args[0], args[1]);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615 }
Simon Horman0d16a402015-01-30 11:22:58 +09002616 else if (*args[0] != 0) {
2617 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621
2622out:
2623 free(errmsg);
2624 return err_code;
2625}
2626
Simon Horman9dc49962015-01-30 11:22:59 +09002627static void free_email_alert(struct proxy *p)
2628{
2629 free(p->email_alert.mailers.name);
2630 p->email_alert.mailers.name = NULL;
2631 free(p->email_alert.from);
2632 p->email_alert.from = NULL;
2633 free(p->email_alert.to);
2634 p->email_alert.to = NULL;
2635 free(p->email_alert.myhostname);
2636 p->email_alert.myhostname = NULL;
2637}
2638
Willy Tarreau3842f002009-06-14 11:39:52 +02002639int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640{
2641 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002642 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002643 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002644 int rc;
2645 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002646 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002647 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002648 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002649 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002650 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 if (!strcmp(args[0], "listen"))
2653 rc = PR_CAP_LISTEN;
2654 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002655 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002656 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002657 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 else
2659 rc = PR_CAP_NONE;
2660
2661 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 if (!*args[1]) {
2663 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002664 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_ABORT;
2667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002669
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002670 err = invalid_char(args[1]);
2671 if (err) {
2672 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2673 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002675 }
2676
Willy Tarreau8f50b682015-05-26 11:45:02 +02002677 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2678 if (curproxy) {
2679 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2681 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002683 }
2684
Vincent Bernat02779b62016-04-03 13:48:43 +02002685 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_ABORT;
2688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002690
Willy Tarreau97cb7802010-01-03 20:23:58 +01002691 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 curproxy->next = proxy;
2693 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002694 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2695 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002696 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002699 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700
William Lallemand6e62fb62015-04-28 16:55:23 +02002701 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2702 if (curproxy->cap & PR_CAP_FE)
2703 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
2706
2707 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002708 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002709 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002710
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002713 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002714 curproxy->no_options = defproxy.no_options;
2715 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002716 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002717 curproxy->except_net = defproxy.except_net;
2718 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002719 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002720 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002722 if (defproxy.fwdfor_hdr_len) {
2723 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2724 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2725 }
2726
Willy Tarreaub86db342009-11-30 11:50:16 +01002727 if (defproxy.orgto_hdr_len) {
2728 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2729 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2730 }
2731
Mark Lamourinec2247f02012-01-04 13:02:01 -05002732 if (defproxy.server_id_hdr_len) {
2733 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2734 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2735 }
2736
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737 if (curproxy->cap & PR_CAP_FE) {
2738 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002739 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002740 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741
2742 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002743 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2744 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745
2746 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002750 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002751 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752 curproxy->fullconn = defproxy.fullconn;
2753 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002754 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002755 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002757 if (defproxy.check_req) {
2758 curproxy->check_req = calloc(1, defproxy.check_len);
2759 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002763 if (defproxy.expect_str) {
2764 curproxy->expect_str = strdup(defproxy.expect_str);
2765 if (defproxy.expect_regex) {
2766 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002767 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2768 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002769 }
2770 }
2771
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773 if (defproxy.cookie_name)
2774 curproxy->cookie_name = strdup(defproxy.cookie_name);
2775 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002776
2777 if (defproxy.dyncookie_key)
2778 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002779 if (defproxy.cookie_domain)
2780 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002781
Willy Tarreau31936852010-10-06 16:59:56 +02002782 if (defproxy.cookie_maxidle)
2783 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2784
2785 if (defproxy.cookie_maxlife)
2786 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2787
Emeric Brun647caf12009-06-30 17:57:00 +02002788 if (defproxy.rdp_cookie_name)
2789 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2790 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2791
Willy Tarreau01732802007-11-01 22:48:15 +01002792 if (defproxy.url_param_name)
2793 curproxy->url_param_name = strdup(defproxy.url_param_name);
2794 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002795
Benoitaffb4812009-03-25 13:02:10 +01002796 if (defproxy.hh_name)
2797 curproxy->hh_name = strdup(defproxy.hh_name);
2798 curproxy->hh_len = defproxy.hh_len;
2799 curproxy->hh_match_domain = defproxy.hh_match_domain;
2800
Willy Tarreauef9a3602012-12-08 22:29:20 +01002801 if (defproxy.conn_src.iface_name)
2802 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2803 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002804 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002805#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002806 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002807#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002808 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002811 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002812 if (defproxy.capture_name)
2813 curproxy->capture_name = strdup(defproxy.capture_name);
2814 curproxy->capture_namelen = defproxy.capture_namelen;
2815 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002819 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002820 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002821 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002822 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002823 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002824 curproxy->mon_net = defproxy.mon_net;
2825 curproxy->mon_mask = defproxy.mon_mask;
2826 if (defproxy.monitor_uri)
2827 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2828 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002829 if (defproxy.defbe.name)
2830 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002831
2832 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002833 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2834 if (curproxy->conf.logformat_string &&
2835 curproxy->conf.logformat_string != default_http_log_format &&
2836 curproxy->conf.logformat_string != default_tcp_log_format &&
2837 curproxy->conf.logformat_string != clf_http_log_format)
2838 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2839
2840 if (defproxy.conf.lfs_file) {
2841 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2842 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2843 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002844
2845 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2846 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2847 if (curproxy->conf.logformat_sd_string &&
2848 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2849 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2850
2851 if (defproxy.conf.lfsd_file) {
2852 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2853 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2854 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855 }
2856
2857 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002858 curproxy->timeout.connect = defproxy.timeout.connect;
2859 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002860 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002861 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002862 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002863 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002864 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002865 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002866 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002867 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002868 }
2869
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002871 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002872
2873 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002874 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002875 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002876 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002877 LIST_INIT(&node->list);
2878 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2879 }
2880
Willy Tarreau62a61232013-04-12 18:13:46 +02002881 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2882 if (curproxy->conf.uniqueid_format_string)
2883 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2884
Dragan Dosen43885c72015-10-01 13:18:13 +02002885 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002886
Willy Tarreau62a61232013-04-12 18:13:46 +02002887 if (defproxy.conf.uif_file) {
2888 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2889 curproxy->conf.uif_line = defproxy.conf.uif_line;
2890 }
William Lallemanda73203e2012-03-12 12:48:57 +01002891
2892 /* copy default header unique id */
2893 if (defproxy.header_unique_id)
2894 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2895
William Lallemand82fe75c2012-10-23 10:25:10 +02002896 /* default compression options */
2897 if (defproxy.comp != NULL) {
2898 curproxy->comp = calloc(1, sizeof(struct comp));
2899 curproxy->comp->algos = defproxy.comp->algos;
2900 curproxy->comp->types = defproxy.comp->types;
2901 }
2902
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002904 curproxy->conf.used_listener_id = EB_ROOT;
2905 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002906
Simon Horman98637e52014-06-20 12:30:16 +09002907 if (defproxy.check_path)
2908 curproxy->check_path = strdup(defproxy.check_path);
2909 if (defproxy.check_command)
2910 curproxy->check_command = strdup(defproxy.check_command);
2911
Simon Horman9dc49962015-01-30 11:22:59 +09002912 if (defproxy.email_alert.mailers.name)
2913 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2914 if (defproxy.email_alert.from)
2915 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2916 if (defproxy.email_alert.to)
2917 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2918 if (defproxy.email_alert.myhostname)
2919 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002920 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002921 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002922
Willy Tarreau93893792009-07-23 13:19:11 +02002923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
2925 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2926 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002927 /* FIXME-20070101: we should do this too at the end of the
2928 * config parsing to free all default values.
2929 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002930 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2931 err_code |= ERR_ABORT;
2932 goto out;
2933 }
2934
Willy Tarreaua534fea2008-08-03 12:19:50 +02002935 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002936 free(defproxy.check_command);
2937 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002938 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002939 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002940 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002941 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002942 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002943 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002944 free(defproxy.capture_name);
2945 free(defproxy.monitor_uri);
2946 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002947 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002948 free(defproxy.fwdfor_hdr_name);
2949 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002950 free(defproxy.orgto_hdr_name);
2951 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002952 free(defproxy.server_id_hdr_name);
2953 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002954 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002955 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002956 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002957 free(defproxy.expect_regex);
2958 defproxy.expect_regex = NULL;
2959 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002960
Willy Tarreau62a61232013-04-12 18:13:46 +02002961 if (defproxy.conf.logformat_string != default_http_log_format &&
2962 defproxy.conf.logformat_string != default_tcp_log_format &&
2963 defproxy.conf.logformat_string != clf_http_log_format)
2964 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002965
Willy Tarreau62a61232013-04-12 18:13:46 +02002966 free(defproxy.conf.uniqueid_format_string);
2967 free(defproxy.conf.lfs_file);
2968 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002969 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002970 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002971
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002972 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2973 free(defproxy.conf.logformat_sd_string);
2974 free(defproxy.conf.lfsd_file);
2975
Willy Tarreaua534fea2008-08-03 12:19:50 +02002976 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002977 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002978
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 /* we cannot free uri_auth because it might already be used */
2980 init_default_instance();
2981 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002982 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2983 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986 }
2987 else if (curproxy == NULL) {
2988 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002992
2993 /* update the current file and line being parsed */
2994 curproxy->conf.args.file = curproxy->conf.file;
2995 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002996
2997 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002998 if (!strcmp(args[0], "server") ||
2999 !strcmp(args[0], "default-server") ||
3000 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02003001 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3002 if (err_code & ERR_FATAL)
3003 goto out;
3004 }
3005 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003006 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003007 int cur_arg;
3008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 if (curproxy == &defproxy) {
3010 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003014 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003015 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016
Willy Tarreau24709282013-03-10 21:32:12 +01003017 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003018 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003023
Willy Tarreaua261e9b2016-12-22 20:44:00 +01003024 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003025
3026 /* use default settings for unix sockets */
3027 bind_conf->ux.uid = global.unix_bind.ux.uid;
3028 bind_conf->ux.gid = global.unix_bind.ux.gid;
3029 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003030
3031 /* NOTE: the following line might create several listeners if there
3032 * are comma-separated IPs or port ranges. So all further processing
3033 * will have to be applied to all listeners created after last_listen.
3034 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003035 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3036 if (errmsg && *errmsg) {
3037 indent_msg(&errmsg, 2);
3038 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003039 }
3040 else
3041 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3042 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003046
Willy Tarreau4348fad2012-09-20 16:48:07 +02003047 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3048 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003049 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003050 }
3051
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003052 cur_arg = 2;
3053 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003054 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003055 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003056 char *err;
3057
Willy Tarreau26982662012-09-12 23:17:10 +02003058 kw = bind_find_kw(args[cur_arg]);
3059 if (kw) {
3060 char *err = NULL;
3061 int code;
3062
3063 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003064 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3065 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003066 cur_arg += 1 + kw->skip ;
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070
Willy Tarreau4348fad2012-09-20 16:48:07 +02003071 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003072 err_code |= code;
3073
3074 if (code) {
3075 if (err && *err) {
3076 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003077 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003078 }
3079 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003080 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3081 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003082 if (code & ERR_FATAL) {
3083 free(err);
3084 cur_arg += 1 + kw->skip;
3085 goto out;
3086 }
3087 }
3088 free(err);
3089 cur_arg += 1 + kw->skip;
3090 continue;
3091 }
3092
Willy Tarreau8638f482012-09-18 18:01:17 +02003093 err = NULL;
3094 if (!bind_dumped) {
3095 bind_dump_kws(&err);
3096 indent_msg(&err, 4);
3097 bind_dumped = 1;
3098 }
3099
3100 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3101 file, linenum, args[0], args[1], args[cur_arg],
3102 err ? " Registered keywords :" : "", err ? err : "");
3103 free(err);
3104
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003107 }
Willy Tarreau93893792009-07-23 13:19:11 +02003108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
3110 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003111 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3113 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003117 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 /* flush useless bits */
3121 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003124 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003125 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003127
William Lallemanddf1425a2015-04-28 20:17:49 +02003128 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3129 goto out;
3130
Willy Tarreau1c47f852006-07-09 08:22:27 +02003131 if (!*args[1]) {
3132 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3133 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003136 }
3137
Willy Tarreaua534fea2008-08-03 12:19:50 +02003138 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003139 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003140 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003141 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003142 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3143
Willy Tarreau93893792009-07-23 13:19:11 +02003144 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3148 goto out;
3149
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3151 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3152 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3153 else {
3154 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003159 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003160 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003161
3162 if (curproxy == &defproxy) {
3163 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003167 }
3168
William Lallemanddf1425a2015-04-28 20:17:49 +02003169 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3170 goto out;
3171
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003172 if (!*args[1]) {
3173 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003177 }
3178
3179 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003180 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003181 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003182
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003183 if (curproxy->uuid <= 0) {
3184 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003185 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003188 }
3189
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003190 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3191 if (node) {
3192 struct proxy *target = container_of(node, struct proxy, conf.id);
3193 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3194 file, linenum, proxy_type_str(curproxy), curproxy->id,
3195 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003200 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003201 else if (!strcmp(args[0], "description")) {
3202 int i, len=0;
3203 char *d;
3204
Cyril Bonté99ed3272010-01-24 23:29:44 +01003205 if (curproxy == &defproxy) {
3206 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3207 file, linenum, args[0]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003212 if (!*args[1]) {
3213 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3214 file, linenum, args[0]);
3215 return -1;
3216 }
3217
Willy Tarreau348acfe2014-04-14 15:00:39 +02003218 for (i = 1; *args[i]; i++)
3219 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003220
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003221 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003222 curproxy->desc = d;
3223
Willy Tarreau348acfe2014-04-14 15:00:39 +02003224 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3225 for (i = 2; *args[i]; i++)
3226 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003227
3228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003230 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 curproxy->state = PR_STSTOPPED;
3233 }
3234 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003235 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 curproxy->state = PR_STNEW;
3238 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003239 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3240 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003241 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003242
3243 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003244 unsigned int low, high;
3245
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003246 if (strcmp(args[cur_arg], "all") == 0) {
3247 set = 0;
3248 break;
3249 }
3250 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003251 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003252 }
3253 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003254 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003255 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003256 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003257 char *dash = strchr(args[cur_arg], '-');
3258
3259 low = high = str2uic(args[cur_arg]);
3260 if (dash)
3261 high = str2uic(dash + 1);
3262
3263 if (high < low) {
3264 unsigned int swap = low;
3265 low = high;
3266 high = swap;
3267 }
3268
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003269 if (low < 1 || high > LONGBITS) {
3270 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3271 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003274 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003275 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003276 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003277 }
3278 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003279 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3280 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003283 }
3284 cur_arg++;
3285 }
3286 curproxy->bind_proc = set;
3287 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003288 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003289 if (curproxy == &defproxy) {
3290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003293 }
3294
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003295 err = invalid_char(args[1]);
3296 if (err) {
3297 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3298 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003300 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003301 }
3302
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003303 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003304 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3305 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003308 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003309 }
3310 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3311
3312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3313 err_code |= ERR_WARN;
3314
3315 if (*(args[1]) == 0) {
3316 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3317 file, linenum, args[0]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321 free(curproxy->dyncookie_key);
3322 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3325 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326
Willy Tarreau977b8e42006-12-29 14:19:17 +01003327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003329
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 if (*(args[1]) == 0) {
3331 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3332 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003336
Willy Tarreau67402132012-05-31 20:40:20 +02003337 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003338 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003339 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003340 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 curproxy->cookie_name = strdup(args[1]);
3342 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003343
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 cur_arg = 2;
3345 while (*(args[cur_arg])) {
3346 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003347 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003350 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
3352 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003353 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 }
3355 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003356 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
3358 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003359 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003361 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003362 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003365 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003367 else if (!strcmp(args[cur_arg], "httponly")) {
3368 curproxy->ck_opts |= PR_CK_HTTPONLY;
3369 }
3370 else if (!strcmp(args[cur_arg], "secure")) {
3371 curproxy->ck_opts |= PR_CK_SECURE;
3372 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003373 else if (!strcmp(args[cur_arg], "domain")) {
3374 if (!*args[cur_arg + 1]) {
3375 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3376 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003379 }
3380
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003381 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003382 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003383 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3384 " dots nor does not start with a dot."
3385 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003386 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003387 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003388 }
3389
3390 err = invalid_domainchar(args[cur_arg + 1]);
3391 if (err) {
3392 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3393 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003396 }
3397
Willy Tarreau68a897b2009-12-03 23:28:34 +01003398 if (!curproxy->cookie_domain) {
3399 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3400 } else {
3401 /* one domain was already specified, add another one by
3402 * building the string which will be returned along with
3403 * the cookie.
3404 */
3405 char *new_ptr;
3406 int new_len = strlen(curproxy->cookie_domain) +
3407 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3408 new_ptr = malloc(new_len);
3409 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3410 free(curproxy->cookie_domain);
3411 curproxy->cookie_domain = new_ptr;
3412 }
Willy Tarreau31936852010-10-06 16:59:56 +02003413 cur_arg++;
3414 }
3415 else if (!strcmp(args[cur_arg], "maxidle")) {
3416 unsigned int maxidle;
3417 const char *res;
3418
3419 if (!*args[cur_arg + 1]) {
3420 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3421 file, linenum, args[cur_arg]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425
3426 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3427 if (res) {
3428 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3429 file, linenum, *res, args[cur_arg]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433 curproxy->cookie_maxidle = maxidle;
3434 cur_arg++;
3435 }
3436 else if (!strcmp(args[cur_arg], "maxlife")) {
3437 unsigned int maxlife;
3438 const char *res;
3439
3440 if (!*args[cur_arg + 1]) {
3441 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3442 file, linenum, args[cur_arg]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446
3447 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3448 if (res) {
3449 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3450 file, linenum, *res, args[cur_arg]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003455 cur_arg++;
3456 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003457 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003458
3459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3460 err_code |= ERR_WARN;
3461 curproxy->ck_opts |= PR_CK_DYNAMIC;
3462 }
3463
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003465 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 +02003466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 }
3470 cur_arg++;
3471 }
Willy Tarreau67402132012-05-31 20:40:20 +02003472 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 }
3477
Willy Tarreau67402132012-05-31 20:40:20 +02003478 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3480 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003483
Willy Tarreau67402132012-05-31 20:40:20 +02003484 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003485 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3486 file, linenum);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003490 else if (!strcmp(args[0], "email-alert")) {
3491 if (*(args[1]) == 0) {
3492 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3493 file, linenum, args[0]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497
3498 if (!strcmp(args[1], "from")) {
3499 if (*(args[1]) == 0) {
3500 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3501 file, linenum, args[1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 free(curproxy->email_alert.from);
3506 curproxy->email_alert.from = strdup(args[2]);
3507 }
3508 else if (!strcmp(args[1], "mailers")) {
3509 if (*(args[1]) == 0) {
3510 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3511 file, linenum, args[1]);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515 free(curproxy->email_alert.mailers.name);
3516 curproxy->email_alert.mailers.name = strdup(args[2]);
3517 }
3518 else if (!strcmp(args[1], "myhostname")) {
3519 if (*(args[1]) == 0) {
3520 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3521 file, linenum, args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 free(curproxy->email_alert.myhostname);
3526 curproxy->email_alert.myhostname = strdup(args[2]);
3527 }
Simon Horman64e34162015-02-06 11:11:57 +09003528 else if (!strcmp(args[1], "level")) {
3529 curproxy->email_alert.level = get_log_level(args[2]);
3530 if (curproxy->email_alert.level < 0) {
3531 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3532 file, linenum, args[1], args[2]);
3533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
3535 }
3536 }
Simon Horman9dc49962015-01-30 11:22:59 +09003537 else if (!strcmp(args[1], "to")) {
3538 if (*(args[1]) == 0) {
3539 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3540 file, linenum, args[1]);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
3544 free(curproxy->email_alert.to);
3545 curproxy->email_alert.to = strdup(args[2]);
3546 }
3547 else {
3548 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3549 file, linenum, args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
Simon Horman64e34162015-02-06 11:11:57 +09003553 /* Indicate that the email_alert is at least partially configured */
3554 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003555 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003556 else if (!strcmp(args[0], "external-check")) {
3557 if (*(args[1]) == 0) {
3558 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3559 file, linenum, args[0]);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
3563
3564 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003565 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003566 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003567 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003568 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3569 file, linenum, args[1]);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
3573 free(curproxy->check_command);
3574 curproxy->check_command = strdup(args[2]);
3575 }
3576 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003577 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003578 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003579 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003580 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3581 file, linenum, args[1]);
3582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
3584 }
3585 free(curproxy->check_path);
3586 curproxy->check_path = strdup(args[2]);
3587 }
3588 else {
3589 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3590 file, linenum, args[1]);
3591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
3593 }
3594 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003595 else if (!strcmp(args[0], "persist")) { /* persist */
3596 if (*(args[1]) == 0) {
3597 Alert("parsing [%s:%d] : missing persist method.\n",
3598 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003601 }
3602
3603 if (!strncmp(args[1], "rdp-cookie", 10)) {
3604 curproxy->options2 |= PR_O2_RDPC_PRST;
3605
Emeric Brunb982a3d2010-01-04 15:45:53 +01003606 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003607 const char *beg, *end;
3608
3609 beg = args[1] + 11;
3610 end = strchr(beg, ')');
3611
William Lallemanddf1425a2015-04-28 20:17:49 +02003612 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3613 goto out;
3614
Emeric Brun647caf12009-06-30 17:57:00 +02003615 if (!end || end == beg) {
3616 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3617 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003620 }
3621
3622 free(curproxy->rdp_cookie_name);
3623 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3624 curproxy->rdp_cookie_len = end-beg;
3625 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003626 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003627 free(curproxy->rdp_cookie_name);
3628 curproxy->rdp_cookie_name = strdup("msts");
3629 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3630 }
3631 else { /* syntax */
3632 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3633 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003636 }
3637 }
3638 else {
3639 Alert("parsing [%s:%d] : unknown persist method.\n",
3640 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003643 }
3644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003646 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003650 else if (!strcmp(args[0], "load-server-state-from-file")) {
3651 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3652 err_code |= ERR_WARN;
3653 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3654 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3655 }
3656 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3657 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3658 }
3659 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3660 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3661 }
3662 else {
3663 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3664 file, linenum, args[0], args[1]);
3665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
3667 }
3668 }
3669 else if (!strcmp(args[0], "server-state-file-name")) {
3670 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3671 err_code |= ERR_WARN;
3672 if (*(args[1]) == 0) {
3673 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3674 file, linenum, args[0]);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678 else if (!strcmp(args[1], "use-backend-name"))
3679 curproxy->server_state_file_name = strdup(curproxy->id);
3680 else
3681 curproxy->server_state_file_name = strdup(args[1]);
3682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003684 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003686
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003688 if (curproxy == &defproxy) {
3689 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693
William Lallemand1a748ae2015-05-19 16:37:23 +02003694 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3695 goto out;
3696
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 if (*(args[4]) == 0) {
3698 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003703 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 curproxy->capture_name = strdup(args[2]);
3705 curproxy->capture_namelen = strlen(curproxy->capture_name);
3706 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 curproxy->to_log |= LW_COOKIE;
3708 }
3709 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3710 struct cap_hdr *hdr;
3711
3712 if (curproxy == &defproxy) {
3713 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 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
3717
William Lallemand1a748ae2015-05-19 16:37:23 +02003718 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3719 goto out;
3720
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3722 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3723 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 }
3727
Vincent Bernat02779b62016-04-03 13:48:43 +02003728 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 hdr->next = curproxy->req_cap;
3730 hdr->name = strdup(args[3]);
3731 hdr->namelen = strlen(args[3]);
3732 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003733 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 hdr->index = curproxy->nb_req_cap++;
3735 curproxy->req_cap = hdr;
3736 curproxy->to_log |= LW_REQHDR;
3737 }
3738 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3739 struct cap_hdr *hdr;
3740
3741 if (curproxy == &defproxy) {
3742 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 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 }
3746
William Lallemand1a748ae2015-05-19 16:37:23 +02003747 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3748 goto out;
3749
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3751 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3752 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003756 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 hdr->next = curproxy->rsp_cap;
3758 hdr->name = strdup(args[3]);
3759 hdr->namelen = strlen(args[3]);
3760 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003761 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 hdr->index = curproxy->nb_rsp_cap++;
3763 curproxy->rsp_cap = hdr;
3764 curproxy->to_log |= LW_RSPHDR;
3765 }
3766 else {
3767 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3768 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
3772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776
William Lallemanddf1425a2015-04-28 20:17:49 +02003777 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3778 goto out;
3779
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 if (*(args[1]) == 0) {
3781 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3782 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
3786 curproxy->conn_retries = atol(args[1]);
3787 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003788 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003789 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003790
3791 if (curproxy == &defproxy) {
3792 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796
Willy Tarreau20b0de52012-12-24 15:45:22 +01003797 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003798 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003799 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3800 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3801 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3802 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003803 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 +01003804 file, linenum, args[0]);
3805 err_code |= ERR_WARN;
3806 }
3807
Willy Tarreauff011f22011-01-06 17:51:27 +01003808 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003809
Willy Tarreauff011f22011-01-06 17:51:27 +01003810 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003811 err_code |= ERR_ALERT | ERR_ABORT;
3812 goto out;
3813 }
3814
Willy Tarreau5002f572014-04-23 01:32:02 +02003815 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003816 err_code |= warnif_cond_conflicts(rule->cond,
3817 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3818 file, linenum);
3819
Willy Tarreauff011f22011-01-06 17:51:27 +01003820 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003821 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003822 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003823 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003824
3825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830
3831 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003832 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003833 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3834 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003835 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3836 file, linenum, args[0]);
3837 err_code |= ERR_WARN;
3838 }
3839
3840 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3841
3842 if (!rule) {
3843 err_code |= ERR_ALERT | ERR_ABORT;
3844 goto out;
3845 }
3846
3847 err_code |= warnif_cond_conflicts(rule->cond,
3848 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3849 file, linenum);
3850
3851 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3852 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003853 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3854 /* set the header name and length into the proxy structure */
3855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3856 err_code |= ERR_WARN;
3857
3858 if (!*args[1]) {
3859 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3860 file, linenum, args[0]);
3861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
3864
3865 /* set the desired header name */
3866 free(curproxy->server_id_hdr_name);
3867 curproxy->server_id_hdr_name = strdup(args[1]);
3868 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3869 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003870 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003871 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003872
Willy Tarreaub099aca2008-10-12 17:26:37 +02003873 if (curproxy == &defproxy) {
3874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003877 }
3878
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003879 /* emulate "block" using "http-request block". Since these rules are supposed to
3880 * be processed before all http-request rules, we put them into their own list
3881 * and will insert them at the end.
3882 */
3883 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3884 if (!rule) {
3885 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003886 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003887 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003888 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3889 err_code |= warnif_cond_conflicts(rule->cond,
3890 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3891 file, linenum);
3892 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003893
3894 if (!already_warned(WARN_BLOCK_DEPRECATED))
3895 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]);
3896
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003897 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003898 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003899 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003900
Cyril Bonté99ed3272010-01-24 23:29:44 +01003901 if (curproxy == &defproxy) {
3902 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906
Willy Tarreaube4653b2015-05-28 15:26:58 +02003907 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003908 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3909 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003912 }
3913
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003914 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003915 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003916 err_code |= warnif_cond_conflicts(rule->cond,
3917 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3918 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003919 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003920 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003921 struct switching_rule *rule;
3922
Willy Tarreaub099aca2008-10-12 17:26:37 +02003923 if (curproxy == &defproxy) {
3924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003927 }
3928
Willy Tarreau55ea7572007-06-17 19:56:27 +02003929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003931
3932 if (*(args[1]) == 0) {
3933 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003936 }
3937
Willy Tarreauf51658d2014-04-23 01:21:56 +02003938 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003939 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreauf51658d2014-04-23 01:21:56 +02003940 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3941 file, linenum, errmsg);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003945
Willy Tarreauf51658d2014-04-23 01:21:56 +02003946 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003947 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003948 else if (*args[2]) {
3949 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3950 file, linenum, args[2]);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
3953 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003954
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003955 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003956 if (!rule) {
3957 Alert("Out of memory error.\n");
3958 goto out;
3959 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003960 rule->cond = cond;
3961 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003962 rule->line = linenum;
3963 rule->file = strdup(file);
3964 if (!rule->file) {
3965 Alert("Out of memory error.\n");
3966 goto out;
3967 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003968 LIST_INIT(&rule->list);
3969 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3970 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003971 else if (strcmp(args[0], "use-server") == 0) {
3972 struct server_rule *rule;
3973
3974 if (curproxy == &defproxy) {
3975 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
3979
3980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3981 err_code |= ERR_WARN;
3982
3983 if (*(args[1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988
3989 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3990 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3991 file, linenum, args[0]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995
Christopher Faulet1b421ea2017-09-22 14:38:56 +02003996 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003997 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3998 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004003 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004004
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004005 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004006 rule->cond = cond;
4007 rule->srv.name = strdup(args[1]);
4008 LIST_INIT(&rule->list);
4009 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4010 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4011 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004012 else if ((!strcmp(args[0], "force-persist")) ||
4013 (!strcmp(args[0], "ignore-persist"))) {
4014 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004015
4016 if (curproxy == &defproxy) {
4017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4023 err_code |= ERR_WARN;
4024
Willy Tarreauef6494c2010-01-28 17:12:36 +01004025 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004026 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4027 file, linenum, args[0]);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
4030 }
4031
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004032 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004033 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4034 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004039 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4040 * where force-persist is applied.
4041 */
4042 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004043
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004044 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004045 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004046 if (!strcmp(args[0], "force-persist")) {
4047 rule->type = PERSIST_TYPE_FORCE;
4048 } else {
4049 rule->type = PERSIST_TYPE_IGNORE;
4050 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004051 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004052 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004053 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054 else if (!strcmp(args[0], "stick-table")) {
4055 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004056 struct proxy *other;
4057
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004058 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004059 if (other) {
4060 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4061 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065
Emeric Brun32da3c42010-09-23 18:39:19 +02004066 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004067 curproxy->table.type = (unsigned int)-1;
4068 while (*args[myidx]) {
4069 const char *err;
4070
4071 if (strcmp(args[myidx], "size") == 0) {
4072 myidx++;
4073 if (!*(args[myidx])) {
4074 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4075 file, linenum, args[myidx-1]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4080 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4081 file, linenum, *err, args[myidx-1]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004085 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004087 else if (strcmp(args[myidx], "peers") == 0) {
4088 myidx++;
Godbach50523162013-12-11 19:48:57 +08004089 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004090 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4091 file, linenum, args[myidx-1]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Godbach50523162013-12-11 19:48:57 +08004094 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004095 curproxy->table.peers.name = strdup(args[myidx++]);
4096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004097 else if (strcmp(args[myidx], "expire") == 0) {
4098 myidx++;
4099 if (!*(args[myidx])) {
4100 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4101 file, linenum, args[myidx-1]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
4105 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4106 if (err) {
4107 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4108 file, linenum, *err, args[myidx-1]);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004112 if (val > INT_MAX) {
4113 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4114 file, linenum, val);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004119 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004120 }
4121 else if (strcmp(args[myidx], "nopurge") == 0) {
4122 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004123 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 }
4125 else if (strcmp(args[myidx], "type") == 0) {
4126 myidx++;
4127 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4128 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4129 file, linenum, args[myidx]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004133 /* myidx already points to next arg */
4134 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004135 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004136 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004137 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004138
4139 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004140 nw = args[myidx];
4141 while (*nw) {
4142 /* the "store" keyword supports a comma-separated list */
4143 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004144 sa = NULL; /* store arg */
4145 while (*nw && *nw != ',') {
4146 if (*nw == '(') {
4147 *nw = 0;
4148 sa = ++nw;
4149 while (*nw != ')') {
4150 if (!*nw) {
4151 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4152 file, linenum, args[0], cw);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156 nw++;
4157 }
4158 *nw = '\0';
4159 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004160 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004161 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004162 if (*nw)
4163 *nw++ = '\0';
4164 type = stktable_get_data_type(cw);
4165 if (type < 0) {
4166 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4167 file, linenum, args[0], cw);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
Willy Tarreauac782882010-06-20 10:41:54 +02004171
4172 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4173 switch (err) {
4174 case PE_NONE: break;
4175 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004176 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4177 file, linenum, args[0], cw);
4178 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004179 break;
4180
4181 case PE_ARG_MISSING:
4182 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4183 file, linenum, args[0], cw);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186
4187 case PE_ARG_NOT_USED:
4188 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4189 file, linenum, args[0], cw);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192
4193 default:
4194 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4195 file, linenum, args[0], cw);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004198 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004199 }
4200 myidx++;
4201 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004202 else {
4203 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4204 file, linenum, args[myidx]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004207 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004208 }
4209
4210 if (!curproxy->table.size) {
4211 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4212 file, linenum);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216
4217 if (curproxy->table.type == (unsigned int)-1) {
4218 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4219 file, linenum);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223 }
4224 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004226 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004227 int myidx = 0;
4228 const char *name = NULL;
4229 int flags;
4230
4231 if (curproxy == &defproxy) {
4232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235 }
4236
4237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4238 err_code |= ERR_WARN;
4239 goto out;
4240 }
4241
4242 myidx++;
4243 if ((strcmp(args[myidx], "store") == 0) ||
4244 (strcmp(args[myidx], "store-request") == 0)) {
4245 myidx++;
4246 flags = STK_IS_STORE;
4247 }
4248 else if (strcmp(args[myidx], "store-response") == 0) {
4249 myidx++;
4250 flags = STK_IS_STORE | STK_ON_RSP;
4251 }
4252 else if (strcmp(args[myidx], "match") == 0) {
4253 myidx++;
4254 flags = STK_IS_MATCH;
4255 }
4256 else if (strcmp(args[myidx], "on") == 0) {
4257 myidx++;
4258 flags = STK_IS_MATCH | STK_IS_STORE;
4259 }
4260 else {
4261 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 if (*(args[myidx]) == 0) {
4267 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004272 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004273 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004274 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004275 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004281 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4282 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4283 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004284 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004285 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004286 goto out;
4287 }
4288 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004289 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4290 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4291 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004292 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004293 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004294 goto out;
4295 }
4296 }
4297
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004298 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004299 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004300
Emeric Brunb982a3d2010-01-04 15:45:53 +01004301 if (strcmp(args[myidx], "table") == 0) {
4302 myidx++;
4303 name = args[myidx++];
4304 }
4305
Willy Tarreauef6494c2010-01-28 17:12:36 +01004306 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004307 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004308 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4309 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004310 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004311 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004312 goto out;
4313 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004314 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004315 else if (*(args[myidx])) {
4316 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4317 file, linenum, args[0], args[myidx]);
4318 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004319 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004320 goto out;
4321 }
Emeric Brun97679e72010-09-23 17:56:44 +02004322 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004323 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004324 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004325 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004326
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004327 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004328 rule->cond = cond;
4329 rule->expr = expr;
4330 rule->flags = flags;
4331 rule->table.name = name ? strdup(name) : NULL;
4332 LIST_INIT(&rule->list);
4333 if (flags & STK_ON_RSP)
4334 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4335 else
4336 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 else if (!strcmp(args[0], "stats")) {
4339 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4340 curproxy->uri_auth = NULL; /* we must detach from the default config */
4341
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004342 if (!*args[1]) {
4343 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004344 } else if (!strcmp(args[1], "admin")) {
4345 struct stats_admin_rule *rule;
4346
4347 if (curproxy == &defproxy) {
4348 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4355 err_code |= ERR_ALERT | ERR_ABORT;
4356 goto out;
4357 }
4358
4359 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4360 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4361 file, linenum, args[0], args[1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
Christopher Faulet1b421ea2017-09-22 14:38:56 +02004365 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004366 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4367 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004372 err_code |= warnif_cond_conflicts(cond,
4373 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4374 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004375
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004376 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004377 rule->cond = cond;
4378 LIST_INIT(&rule->list);
4379 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 } else if (!strcmp(args[1], "uri")) {
4381 if (*(args[2]) == 0) {
4382 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_ABORT;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
4390 } else if (!strcmp(args[1], "realm")) {
4391 if (*(args[2]) == 0) {
4392 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_ABORT;
4398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004400 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004401 unsigned interval;
4402
4403 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4404 if (err) {
4405 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4406 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004409 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_ABORT;
4412 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004413 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004414 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004415 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004416
4417 if (curproxy == &defproxy) {
4418 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422
4423 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4425 err_code |= ERR_ALERT | ERR_ABORT;
4426 goto out;
4427 }
4428
Willy Tarreauff011f22011-01-06 17:51:27 +01004429 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004430 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004431 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4432 file, linenum, args[0]);
4433 err_code |= ERR_WARN;
4434 }
4435
Willy Tarreauff011f22011-01-06 17:51:27 +01004436 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004437
Willy Tarreauff011f22011-01-06 17:51:27 +01004438 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004439 err_code |= ERR_ALERT | ERR_ABORT;
4440 goto out;
4441 }
4442
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004443 err_code |= warnif_cond_conflicts(rule->cond,
4444 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4445 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004446 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004447
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 } else if (!strcmp(args[1], "auth")) {
4449 if (*(args[2]) == 0) {
4450 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4454 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_ABORT;
4456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
4458 } else if (!strcmp(args[1], "scope")) {
4459 if (*(args[2]) == 0) {
4460 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4464 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_ABORT;
4466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
4468 } else if (!strcmp(args[1], "enable")) {
4469 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004474 } else if (!strcmp(args[1], "hide-version")) {
4475 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_ABORT;
4478 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004479 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004480 } else if (!strcmp(args[1], "show-legends")) {
4481 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4482 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4483 err_code |= ERR_ALERT | ERR_ABORT;
4484 goto out;
4485 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004486 } else if (!strcmp(args[1], "show-node")) {
4487
4488 if (*args[2]) {
4489 int i;
4490 char c;
4491
4492 for (i=0; args[2][i]; i++) {
4493 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004494 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4495 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004496 break;
4497 }
4498
4499 if (!i || args[2][i]) {
4500 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4501 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4502 file, linenum, args[0], args[1]);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
4506 }
4507
4508 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4509 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4510 err_code |= ERR_ALERT | ERR_ABORT;
4511 goto out;
4512 }
4513 } else if (!strcmp(args[1], "show-desc")) {
4514 char *desc = NULL;
4515
4516 if (*args[2]) {
4517 int i, len=0;
4518 char *d;
4519
Willy Tarreau348acfe2014-04-14 15:00:39 +02004520 for (i = 2; *args[i]; i++)
4521 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004522
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004523 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004524
Willy Tarreau348acfe2014-04-14 15:00:39 +02004525 d += snprintf(d, desc + len - d, "%s", args[2]);
4526 for (i = 3; *args[i]; i++)
4527 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528 }
4529
4530 if (!*args[2] && !global.desc)
4531 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4532 file, linenum, args[1]);
4533 else {
4534 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4535 free(desc);
4536 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4537 err_code |= ERR_ALERT | ERR_ABORT;
4538 goto out;
4539 }
4540 free(desc);
4541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004543stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004544 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 +01004545 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 }
4549 }
4550 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004551 int optnum;
4552
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004553 if (*(args[1]) == '\0') {
4554 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004559
4560 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4561 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004562 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4563 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4564 file, linenum, cfg_opts[optnum].name);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004568 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4569 goto out;
4570
Willy Tarreau93893792009-07-23 13:19:11 +02004571 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4572 err_code |= ERR_WARN;
4573 goto out;
4574 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004575
Willy Tarreau3842f002009-06-14 11:39:52 +02004576 curproxy->no_options &= ~cfg_opts[optnum].val;
4577 curproxy->options &= ~cfg_opts[optnum].val;
4578
4579 switch (kwm) {
4580 case KWM_STD:
4581 curproxy->options |= cfg_opts[optnum].val;
4582 break;
4583 case KWM_NO:
4584 curproxy->no_options |= cfg_opts[optnum].val;
4585 break;
4586 case KWM_DEF: /* already cleared */
4587 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004588 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004589
Willy Tarreau93893792009-07-23 13:19:11 +02004590 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004591 }
4592 }
4593
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004594 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4595 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004596 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4597 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4598 file, linenum, cfg_opts2[optnum].name);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004602 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4603 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004604 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4605 err_code |= ERR_WARN;
4606 goto out;
4607 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004608
Willy Tarreau3842f002009-06-14 11:39:52 +02004609 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4610 curproxy->options2 &= ~cfg_opts2[optnum].val;
4611
4612 switch (kwm) {
4613 case KWM_STD:
4614 curproxy->options2 |= cfg_opts2[optnum].val;
4615 break;
4616 case KWM_NO:
4617 curproxy->no_options2 |= cfg_opts2[optnum].val;
4618 break;
4619 case KWM_DEF: /* already cleared */
4620 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004621 }
Willy Tarreau93893792009-07-23 13:19:11 +02004622 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004623 }
4624 }
4625
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004626 /* HTTP options override each other. They can be cancelled using
4627 * "no option xxx" which only switches to default mode if the mode
4628 * was this one (useful for cancelling options set in defaults
4629 * sections).
4630 */
4631 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004632 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4633 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004634 if (kwm == KWM_STD) {
4635 curproxy->options &= ~PR_O_HTTP_MODE;
4636 curproxy->options |= PR_O_HTTP_PCL;
4637 goto out;
4638 }
4639 else if (kwm == KWM_NO) {
4640 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4641 curproxy->options &= ~PR_O_HTTP_MODE;
4642 goto out;
4643 }
4644 }
4645 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004646 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4647 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004648 if (kwm == KWM_STD) {
4649 curproxy->options &= ~PR_O_HTTP_MODE;
4650 curproxy->options |= PR_O_HTTP_FCL;
4651 goto out;
4652 }
4653 else if (kwm == KWM_NO) {
4654 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4655 curproxy->options &= ~PR_O_HTTP_MODE;
4656 goto out;
4657 }
4658 }
4659 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004660 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4661 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004662 if (kwm == KWM_STD) {
4663 curproxy->options &= ~PR_O_HTTP_MODE;
4664 curproxy->options |= PR_O_HTTP_SCL;
4665 goto out;
4666 }
4667 else if (kwm == KWM_NO) {
4668 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4669 curproxy->options &= ~PR_O_HTTP_MODE;
4670 goto out;
4671 }
4672 }
4673 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004674 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4675 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004676 if (kwm == KWM_STD) {
4677 curproxy->options &= ~PR_O_HTTP_MODE;
4678 curproxy->options |= PR_O_HTTP_KAL;
4679 goto out;
4680 }
4681 else if (kwm == KWM_NO) {
4682 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4683 curproxy->options &= ~PR_O_HTTP_MODE;
4684 goto out;
4685 }
4686 }
4687 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004688 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4689 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004690 if (kwm == KWM_STD) {
4691 curproxy->options &= ~PR_O_HTTP_MODE;
4692 curproxy->options |= PR_O_HTTP_TUN;
4693 goto out;
4694 }
4695 else if (kwm == KWM_NO) {
4696 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4697 curproxy->options &= ~PR_O_HTTP_MODE;
4698 goto out;
4699 }
4700 }
4701
Joseph Lynch726ab712015-05-11 23:25:34 -07004702 /* Redispatch can take an integer argument that control when the
4703 * resispatch occurs. All values are relative to the retries option.
4704 * This can be cancelled using "no option xxx".
4705 */
4706 if (strcmp(args[1], "redispatch") == 0) {
4707 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4708 err_code |= ERR_WARN;
4709 goto out;
4710 }
4711
4712 curproxy->no_options &= ~PR_O_REDISP;
4713 curproxy->options &= ~PR_O_REDISP;
4714
4715 switch (kwm) {
4716 case KWM_STD:
4717 curproxy->options |= PR_O_REDISP;
4718 curproxy->redispatch_after = -1;
4719 if(*args[2]) {
4720 curproxy->redispatch_after = atol(args[2]);
4721 }
4722 break;
4723 case KWM_NO:
4724 curproxy->no_options |= PR_O_REDISP;
4725 curproxy->redispatch_after = 0;
4726 break;
4727 case KWM_DEF: /* already cleared */
4728 break;
4729 }
4730 goto out;
4731 }
4732
Willy Tarreau3842f002009-06-14 11:39:52 +02004733 if (kwm != KWM_STD) {
4734 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004735 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004738 }
4739
Emeric Brun3a058f32009-06-30 18:26:00 +02004740 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004741 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004743 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004744 if (*(args[2]) != '\0') {
4745 if (!strcmp(args[2], "clf")) {
4746 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004747 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004748 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004749 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004752 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004753 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4754 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004755 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004756 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4757 char *oldlogformat = "log-format";
4758 char *clflogformat = "";
4759
4760 if (curproxy->conf.logformat_string == default_http_log_format)
4761 oldlogformat = "option httplog";
4762 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4763 oldlogformat = "option tcplog";
4764 else if (curproxy->conf.logformat_string == clf_http_log_format)
4765 oldlogformat = "option httplog clf";
4766 if (logformat == clf_http_log_format)
4767 clflogformat = " clf";
4768 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4769 file, linenum, clflogformat, oldlogformat);
4770 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004771 if (curproxy->conf.logformat_string != default_http_log_format &&
4772 curproxy->conf.logformat_string != default_tcp_log_format &&
4773 curproxy->conf.logformat_string != clf_http_log_format)
4774 free(curproxy->conf.logformat_string);
4775 curproxy->conf.logformat_string = logformat;
4776
4777 free(curproxy->conf.lfs_file);
4778 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4779 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004780 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004781 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004782 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4783 char *oldlogformat = "log-format";
4784
4785 if (curproxy->conf.logformat_string == default_http_log_format)
4786 oldlogformat = "option httplog";
4787 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4788 oldlogformat = "option tcplog";
4789 else if (curproxy->conf.logformat_string == clf_http_log_format)
4790 oldlogformat = "option httplog clf";
4791 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4792 file, linenum, oldlogformat);
4793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004795 if (curproxy->conf.logformat_string != default_http_log_format &&
4796 curproxy->conf.logformat_string != default_tcp_log_format &&
4797 curproxy->conf.logformat_string != clf_http_log_format)
4798 free(curproxy->conf.logformat_string);
4799 curproxy->conf.logformat_string = default_tcp_log_format;
4800
4801 free(curproxy->conf.lfs_file);
4802 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4803 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004804
4805 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4806 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004809 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004810 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004811 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004812
William Lallemanddf1425a2015-04-28 20:17:49 +02004813 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4814 goto out;
4815
Willy Tarreau13943ab2006-12-31 00:24:10 +01004816 if (curproxy->cap & PR_CAP_FE)
4817 curproxy->options |= PR_O_TCP_CLI_KA;
4818 if (curproxy->cap & PR_CAP_BE)
4819 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
4821 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004823 err_code |= ERR_WARN;
4824
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004826 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004827 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004828 curproxy->options2 &= ~PR_O2_CHK_ANY;
4829 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 if (!*args[2]) { /* no argument */
4831 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4832 curproxy->check_len = strlen(DEF_CHECK_REQ);
4833 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004834 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004835 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004837 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004839 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 if (*args[4])
4841 reqlen += strlen(args[4]);
4842 else
4843 reqlen += strlen("HTTP/1.0");
4844
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004845 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004847 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004849 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4850 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004851 }
4852 else if (!strcmp(args[1], "ssl-hello-chk")) {
4853 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004856
Willy Tarreaua534fea2008-08-03 12:19:50 +02004857 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004858 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004859 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004860 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004861
4862 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
Willy Tarreau23677902007-05-08 23:50:35 +02004865 else if (!strcmp(args[1], "smtpchk")) {
4866 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004867 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004869 curproxy->options2 &= ~PR_O2_CHK_ANY;
4870 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004871
4872 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4873 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4874 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4875 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4876 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4877 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004878 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004879 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4880 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4881 } else {
4882 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4883 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4884 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4885 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4886 }
4887 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004888 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4889 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004890 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004891 else if (!strcmp(args[1], "pgsql-check")) {
4892 /* use PostgreSQL request to check servers' health */
4893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4894 err_code |= ERR_WARN;
4895
4896 free(curproxy->check_req);
4897 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004898 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004899 curproxy->options2 |= PR_O2_PGSQL_CHK;
4900
4901 if (*(args[2])) {
4902 int cur_arg = 2;
4903
4904 while (*(args[cur_arg])) {
4905 if (strcmp(args[cur_arg], "user") == 0) {
4906 char * packet;
4907 uint32_t packet_len;
4908 uint32_t pv;
4909
4910 /* suboption header - needs additional argument for it */
4911 if (*(args[cur_arg+1]) == 0) {
4912 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4913 file, linenum, args[0], args[1], args[cur_arg]);
4914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916 }
4917
4918 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4919 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4920 pv = htonl(0x30000); /* protocol version 3.0 */
4921
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004922 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004923
4924 memcpy(packet + 4, &pv, 4);
4925
4926 /* copy "user" */
4927 memcpy(packet + 8, "user", 4);
4928
4929 /* copy username */
4930 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4931
4932 free(curproxy->check_req);
4933 curproxy->check_req = packet;
4934 curproxy->check_len = packet_len;
4935
4936 packet_len = htonl(packet_len);
4937 memcpy(packet, &packet_len, 4);
4938 cur_arg += 2;
4939 } else {
4940 /* unknown suboption - catchall */
4941 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4942 file, linenum, args[0], args[1]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946 } /* end while loop */
4947 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004948 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4949 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004950 }
4951
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004952 else if (!strcmp(args[1], "redis-check")) {
4953 /* use REDIS PING request to check servers' health */
4954 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4955 err_code |= ERR_WARN;
4956
4957 free(curproxy->check_req);
4958 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004959 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004960 curproxy->options2 |= PR_O2_REDIS_CHK;
4961
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004962 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004963 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4964 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004965
4966 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4967 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004968 }
4969
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004970 else if (!strcmp(args[1], "mysql-check")) {
4971 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4973 err_code |= ERR_WARN;
4974
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004975 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004976 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004977 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004978 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004979
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004980 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004981 * const char mysql40_client_auth_pkt[] = {
4982 * "\x0e\x00\x00" // packet length
4983 * "\x01" // packet number
4984 * "\x00\x00" // client capabilities
4985 * "\x00\x00\x01" // max packet
4986 * "haproxy\x00" // username (null terminated string)
4987 * "\x00" // filler (always 0x00)
4988 * "\x01\x00\x00" // packet length
4989 * "\x00" // packet number
4990 * "\x01" // COM_QUIT command
4991 * };
4992 */
4993
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004994 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4995 * const char mysql41_client_auth_pkt[] = {
4996 * "\x0e\x00\x00\" // packet length
4997 * "\x01" // packet number
4998 * "\x00\x00\x00\x00" // client capabilities
4999 * "\x00\x00\x00\x01" // max packet
5000 * "\x21" // character set (UTF-8)
5001 * char[23] // All zeroes
5002 * "haproxy\x00" // username (null terminated string)
5003 * "\x00" // filler (always 0x00)
5004 * "\x01\x00\x00" // packet length
5005 * "\x00" // packet number
5006 * "\x01" // COM_QUIT command
5007 * };
5008 */
5009
5010
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005011 if (*(args[2])) {
5012 int cur_arg = 2;
5013
5014 while (*(args[cur_arg])) {
5015 if (strcmp(args[cur_arg], "user") == 0) {
5016 char *mysqluser;
5017 int packetlen, reqlen, userlen;
5018
5019 /* suboption header - needs additional argument for it */
5020 if (*(args[cur_arg+1]) == 0) {
5021 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5022 file, linenum, args[0], args[1], args[cur_arg]);
5023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
5025 }
5026 mysqluser = args[cur_arg + 1];
5027 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005028
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005029 if (*(args[cur_arg+2])) {
5030 if (!strcmp(args[cur_arg+2], "post-41")) {
5031 packetlen = userlen + 7 + 27;
5032 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005033
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005034 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005035 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005036 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005037
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005038 snprintf(curproxy->check_req, 4, "%c%c%c",
5039 ((unsigned char) packetlen & 0xff),
5040 ((unsigned char) (packetlen >> 8) & 0xff),
5041 ((unsigned char) (packetlen >> 16) & 0xff));
5042
5043 curproxy->check_req[3] = 1;
5044 curproxy->check_req[5] = 130;
5045 curproxy->check_req[11] = 1;
5046 curproxy->check_req[12] = 33;
5047 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5048 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5049 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5050 cur_arg += 3;
5051 } else {
5052 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
5055 }
5056 } else {
5057 packetlen = userlen + 7;
5058 reqlen = packetlen + 9;
5059
5060 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005061 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005062 curproxy->check_len = reqlen;
5063
5064 snprintf(curproxy->check_req, 4, "%c%c%c",
5065 ((unsigned char) packetlen & 0xff),
5066 ((unsigned char) (packetlen >> 8) & 0xff),
5067 ((unsigned char) (packetlen >> 16) & 0xff));
5068
5069 curproxy->check_req[3] = 1;
5070 curproxy->check_req[5] = 128;
5071 curproxy->check_req[8] = 1;
5072 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5073 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5074 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5075 cur_arg += 2;
5076 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005077 } else {
5078 /* unknown suboption - catchall */
5079 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5080 file, linenum, args[0], args[1]);
5081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084 } /* end while loop */
5085 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005086 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005087 else if (!strcmp(args[1], "ldap-check")) {
5088 /* use LDAP request to check servers' health */
5089 free(curproxy->check_req);
5090 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005091 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005092 curproxy->options2 |= PR_O2_LDAP_CHK;
5093
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005094 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005095 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5096 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005097 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5098 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005099 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005100 else if (!strcmp(args[1], "spop-check")) {
5101 if (curproxy == &defproxy) {
5102 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5103 file, linenum, args[0], args[1]);
5104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
5106 }
5107 if (curproxy->cap & PR_CAP_FE) {
5108 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5109 file, linenum, args[0], args[1]);
5110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
5113
5114 /* use SPOE request to check servers' health */
5115 free(curproxy->check_req);
5116 curproxy->check_req = NULL;
5117 curproxy->options2 &= ~PR_O2_CHK_ANY;
5118 curproxy->options2 |= PR_O2_SPOP_CHK;
5119
Christopher Faulet8ef75252017-02-20 22:56:03 +01005120 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005121 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
5125 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5126 goto out;
5127 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005128 else if (!strcmp(args[1], "tcp-check")) {
5129 /* use raw TCPCHK send/expect to check servers' health */
5130 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5131 err_code |= ERR_WARN;
5132
5133 free(curproxy->check_req);
5134 curproxy->check_req = NULL;
5135 curproxy->options2 &= ~PR_O2_CHK_ANY;
5136 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005137 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5138 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005139 }
Simon Horman98637e52014-06-20 12:30:16 +09005140 else if (!strcmp(args[1], "external-check")) {
5141 /* excute an external command to check servers' health */
5142 free(curproxy->check_req);
5143 curproxy->check_req = NULL;
5144 curproxy->options2 &= ~PR_O2_CHK_ANY;
5145 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005146 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5147 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005148 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005149 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005150 int cur_arg;
5151
5152 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5153 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005154 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005155
Willy Tarreau87cf5142011-08-19 22:57:24 +02005156 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005157
5158 free(curproxy->fwdfor_hdr_name);
5159 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5160 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5161
5162 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5163 cur_arg = 2;
5164 while (*(args[cur_arg])) {
5165 if (!strcmp(args[cur_arg], "except")) {
5166 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005167 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005168 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5169 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005172 }
5173 /* flush useless bits */
5174 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005175 cur_arg += 2;
5176 } else if (!strcmp(args[cur_arg], "header")) {
5177 /* suboption header - needs additional argument for it */
5178 if (*(args[cur_arg+1]) == 0) {
5179 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5180 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005183 }
5184 free(curproxy->fwdfor_hdr_name);
5185 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5186 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5187 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005188 } else if (!strcmp(args[cur_arg], "if-none")) {
5189 curproxy->options &= ~PR_O_FF_ALWAYS;
5190 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005191 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005192 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005193 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005194 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005197 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005198 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005199 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005200 else if (!strcmp(args[1], "originalto")) {
5201 int cur_arg;
5202
5203 /* insert x-original-to field, but not for the IP address listed as an except.
5204 * set default options (ie: bitfield, header name, etc)
5205 */
5206
5207 curproxy->options |= PR_O_ORGTO;
5208
5209 free(curproxy->orgto_hdr_name);
5210 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5211 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5212
Willy Tarreau87cf5142011-08-19 22:57:24 +02005213 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005214 cur_arg = 2;
5215 while (*(args[cur_arg])) {
5216 if (!strcmp(args[cur_arg], "except")) {
5217 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005218 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 +02005219 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5220 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005223 }
5224 /* flush useless bits */
5225 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5226 cur_arg += 2;
5227 } else if (!strcmp(args[cur_arg], "header")) {
5228 /* suboption header - needs additional argument for it */
5229 if (*(args[cur_arg+1]) == 0) {
5230 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5231 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005234 }
5235 free(curproxy->orgto_hdr_name);
5236 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5237 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5238 cur_arg += 2;
5239 } else {
5240 /* unknown suboption - catchall */
5241 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5242 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005245 }
5246 } /* end while loop */
5247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 else {
5249 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
Willy Tarreau93893792009-07-23 13:19:11 +02005253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005255 else if (!strcmp(args[0], "default_backend")) {
5256 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005258
5259 if (*(args[1]) == 0) {
5260 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005263 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005264 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005265 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005266
5267 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5268 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005273
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005274 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5275 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 +01005276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 /* enable reconnections to dispatch */
5279 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005280
5281 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005284 else if (!strcmp(args[0], "http-reuse")) {
5285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5286 err_code |= ERR_WARN;
5287
5288 if (strcmp(args[1], "never") == 0) {
5289 /* enable a graceful server shutdown on an HTTP 404 response */
5290 curproxy->options &= ~PR_O_REUSE_MASK;
5291 curproxy->options |= PR_O_REUSE_NEVR;
5292 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5293 goto out;
5294 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005295 else if (strcmp(args[1], "safe") == 0) {
5296 /* enable a graceful server shutdown on an HTTP 404 response */
5297 curproxy->options &= ~PR_O_REUSE_MASK;
5298 curproxy->options |= PR_O_REUSE_SAFE;
5299 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5300 goto out;
5301 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005302 else if (strcmp(args[1], "aggressive") == 0) {
5303 curproxy->options &= ~PR_O_REUSE_MASK;
5304 curproxy->options |= PR_O_REUSE_AGGR;
5305 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5306 goto out;
5307 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005308 else if (strcmp(args[1], "always") == 0) {
5309 /* enable a graceful server shutdown on an HTTP 404 response */
5310 curproxy->options &= ~PR_O_REUSE_MASK;
5311 curproxy->options |= PR_O_REUSE_ALWS;
5312 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5313 goto out;
5314 }
5315 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005316 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005321 else if (!strcmp(args[0], "http-check")) {
5322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005323 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005324
5325 if (strcmp(args[1], "disable-on-404") == 0) {
5326 /* enable a graceful server shutdown on an HTTP 404 response */
5327 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005328 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5329 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005330 }
Willy Tarreauef781042010-01-27 11:53:01 +01005331 else if (strcmp(args[1], "send-state") == 0) {
5332 /* enable emission of the apparent state of a server in HTTP checks */
5333 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005334 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5335 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005336 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005337 else if (strcmp(args[1], "expect") == 0) {
5338 const char *ptr_arg;
5339 int cur_arg;
5340
5341 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5342 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 cur_arg = 2;
5348 /* consider exclamation marks, sole or at the beginning of a word */
5349 while (*(ptr_arg = args[cur_arg])) {
5350 while (*ptr_arg == '!') {
5351 curproxy->options2 ^= PR_O2_EXP_INV;
5352 ptr_arg++;
5353 }
5354 if (*ptr_arg)
5355 break;
5356 cur_arg++;
5357 }
5358 /* now ptr_arg points to the beginning of a word past any possible
5359 * exclamation mark, and cur_arg is the argument which holds this word.
5360 */
5361 if (strcmp(ptr_arg, "status") == 0) {
5362 if (!*(args[cur_arg + 1])) {
5363 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5364 file, linenum, args[0], args[1], ptr_arg);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005369 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005370 curproxy->expect_str = strdup(args[cur_arg + 1]);
5371 }
5372 else if (strcmp(ptr_arg, "string") == 0) {
5373 if (!*(args[cur_arg + 1])) {
5374 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5375 file, linenum, args[0], args[1], ptr_arg);
5376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378 }
5379 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005380 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005381 curproxy->expect_str = strdup(args[cur_arg + 1]);
5382 }
5383 else if (strcmp(ptr_arg, "rstatus") == 0) {
5384 if (!*(args[cur_arg + 1])) {
5385 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5386 file, linenum, args[0], args[1], ptr_arg);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005391 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005392 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005393 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005394 free(curproxy->expect_regex);
5395 curproxy->expect_regex = NULL;
5396 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005397 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005398 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5399 error = NULL;
5400 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5401 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5402 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5403 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407 }
5408 else if (strcmp(ptr_arg, "rstring") == 0) {
5409 if (!*(args[cur_arg + 1])) {
5410 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5411 file, linenum, args[0], args[1], ptr_arg);
5412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
5414 }
5415 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005416 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005417 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005418 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005419 free(curproxy->expect_regex);
5420 curproxy->expect_regex = NULL;
5421 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005422 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005423 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5424 error = NULL;
5425 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5426 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5427 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5428 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 }
5433 else {
5434 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5435 file, linenum, args[0], args[1], ptr_arg);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005440 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005441 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 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005444 }
5445 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005446 else if (!strcmp(args[0], "tcp-check")) {
5447 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5448 err_code |= ERR_WARN;
5449
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005450 if (strcmp(args[1], "comment") == 0) {
5451 int cur_arg;
5452 struct tcpcheck_rule *tcpcheck;
5453
5454 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005455 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005456 tcpcheck->action = TCPCHK_ACT_COMMENT;
5457
5458 if (!*args[cur_arg + 1]) {
5459 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5460 file, linenum, args[cur_arg]);
5461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
5463 }
5464
5465 tcpcheck->comment = strdup(args[cur_arg + 1]);
5466
5467 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005468 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5469 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005470 }
5471 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005472 const char *ptr_arg;
5473 int cur_arg;
5474 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005475
5476 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005477 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5478 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5479 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5480 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5481 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005482
Willy Tarreau5581c272015-05-13 12:24:53 +02005483 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5484 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5485 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5486 file, linenum);
5487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005489 }
5490
5491 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005492 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005493 tcpcheck->action = TCPCHK_ACT_CONNECT;
5494
5495 /* parsing each parameters to fill up the rule */
5496 while (*(ptr_arg = args[cur_arg])) {
5497 /* tcp port */
5498 if (strcmp(args[cur_arg], "port") == 0) {
5499 if ( (atol(args[cur_arg + 1]) > 65535) ||
5500 (atol(args[cur_arg + 1]) < 1) ){
5501 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5502 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 tcpcheck->port = atol(args[cur_arg + 1]);
5507 cur_arg += 2;
5508 }
5509 /* send proxy protocol */
5510 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5511 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5512 cur_arg++;
5513 }
5514#ifdef USE_OPENSSL
5515 else if (strcmp(args[cur_arg], "ssl") == 0) {
5516 curproxy->options |= PR_O_TCPCHK_SSL;
5517 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5518 cur_arg++;
5519 }
5520#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005521 /* comment for this tcpcheck line */
5522 else if (strcmp(args[cur_arg], "comment") == 0) {
5523 if (!*args[cur_arg + 1]) {
5524 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5525 file, linenum, args[cur_arg]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
5529 tcpcheck->comment = strdup(args[cur_arg + 1]);
5530 cur_arg += 2;
5531 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005532 else {
5533#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005534 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 +01005535#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005536 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 +01005537#endif /* USE_OPENSSL */
5538 file, linenum, args[0], args[1], args[cur_arg]);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
5542
5543 }
5544
5545 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5546 }
5547 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005548 if (! *(args[2]) ) {
5549 /* SEND string expected */
5550 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5551 file, linenum, args[0], args[1], args[2]);
5552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
5554 } else {
5555 struct tcpcheck_rule *tcpcheck;
5556
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005557 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005558
5559 tcpcheck->action = TCPCHK_ACT_SEND;
5560 tcpcheck->string_len = strlen(args[2]);
5561 tcpcheck->string = strdup(args[2]);
5562 tcpcheck->expect_regex = NULL;
5563
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005564 /* comment for this tcpcheck line */
5565 if (strcmp(args[3], "comment") == 0) {
5566 if (!*args[4]) {
5567 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5568 file, linenum, args[3]);
5569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
5571 }
5572 tcpcheck->comment = strdup(args[4]);
5573 }
5574
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005575 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5576 }
5577 }
5578 else if (strcmp(args[1], "send-binary") == 0) {
5579 if (! *(args[2]) ) {
5580 /* SEND binary string expected */
5581 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5582 file, linenum, args[0], args[1], args[2]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 } else {
5586 struct tcpcheck_rule *tcpcheck;
5587 char *err = NULL;
5588
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005589 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590
5591 tcpcheck->action = TCPCHK_ACT_SEND;
5592 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5593 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5594 file, linenum, args[0], args[1], args[2], err);
5595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
5597 }
5598 tcpcheck->expect_regex = NULL;
5599
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005600 /* comment for this tcpcheck line */
5601 if (strcmp(args[3], "comment") == 0) {
5602 if (!*args[4]) {
5603 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5604 file, linenum, args[3]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
5608 tcpcheck->comment = strdup(args[4]);
5609 }
5610
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005611 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5612 }
5613 }
5614 else if (strcmp(args[1], "expect") == 0) {
5615 const char *ptr_arg;
5616 int cur_arg;
5617 int inverse = 0;
5618
5619 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5620 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
5623 }
5624
5625 cur_arg = 2;
5626 /* consider exclamation marks, sole or at the beginning of a word */
5627 while (*(ptr_arg = args[cur_arg])) {
5628 while (*ptr_arg == '!') {
5629 inverse = !inverse;
5630 ptr_arg++;
5631 }
5632 if (*ptr_arg)
5633 break;
5634 cur_arg++;
5635 }
5636 /* now ptr_arg points to the beginning of a word past any possible
5637 * exclamation mark, and cur_arg is the argument which holds this word.
5638 */
5639 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005640 struct tcpcheck_rule *tcpcheck;
5641 char *err = NULL;
5642
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005643 if (!*(args[cur_arg + 1])) {
5644 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5645 file, linenum, args[0], args[1], ptr_arg);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005650 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651
5652 tcpcheck->action = TCPCHK_ACT_EXPECT;
5653 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5654 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5655 file, linenum, args[0], args[1], args[2], err);
5656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659 tcpcheck->expect_regex = NULL;
5660 tcpcheck->inverse = inverse;
5661
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005662 /* tcpcheck comment */
5663 cur_arg += 2;
5664 if (strcmp(args[cur_arg], "comment") == 0) {
5665 if (!*args[cur_arg + 1]) {
5666 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5667 file, linenum, args[cur_arg + 1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671 tcpcheck->comment = strdup(args[cur_arg + 1]);
5672 }
5673
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005674 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5675 }
5676 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005677 struct tcpcheck_rule *tcpcheck;
5678
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005679 if (!*(args[cur_arg + 1])) {
5680 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5681 file, linenum, args[0], args[1], ptr_arg);
5682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
5684 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005686 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005687
5688 tcpcheck->action = TCPCHK_ACT_EXPECT;
5689 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5690 tcpcheck->string = strdup(args[cur_arg + 1]);
5691 tcpcheck->expect_regex = NULL;
5692 tcpcheck->inverse = inverse;
5693
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005694 /* tcpcheck comment */
5695 cur_arg += 2;
5696 if (strcmp(args[cur_arg], "comment") == 0) {
5697 if (!*args[cur_arg + 1]) {
5698 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5699 file, linenum, args[cur_arg + 1]);
5700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
5703 tcpcheck->comment = strdup(args[cur_arg + 1]);
5704 }
5705
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005706 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5707 }
5708 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005709 struct tcpcheck_rule *tcpcheck;
5710
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005711 if (!*(args[cur_arg + 1])) {
5712 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5713 file, linenum, args[0], args[1], ptr_arg);
5714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
5716 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005717
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005718 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005719
5720 tcpcheck->action = TCPCHK_ACT_EXPECT;
5721 tcpcheck->string_len = 0;
5722 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005723 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5724 error = NULL;
5725 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5726 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5727 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5728 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
5731 }
5732 tcpcheck->inverse = inverse;
5733
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005734 /* tcpcheck comment */
5735 cur_arg += 2;
5736 if (strcmp(args[cur_arg], "comment") == 0) {
5737 if (!*args[cur_arg + 1]) {
5738 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5739 file, linenum, args[cur_arg + 1]);
5740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
5742 }
5743 tcpcheck->comment = strdup(args[cur_arg + 1]);
5744 }
5745
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005746 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5747 }
5748 else {
5749 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5750 file, linenum, args[0], args[1], ptr_arg);
5751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
5753 }
5754 }
5755 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005756 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005757 err_code |= ERR_ALERT | ERR_FATAL;
5758 goto out;
5759 }
5760 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005761 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005762 if (curproxy == &defproxy) {
5763 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005766 }
5767
Willy Tarreaub80c2302007-11-30 20:51:32 +01005768 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005770
5771 if (strcmp(args[1], "fail") == 0) {
5772 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005773 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005774 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5775 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005778 }
5779
Christopher Faulet1b421ea2017-09-22 14:38:56 +02005780 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005781 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5782 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005783 err_code |= ERR_ALERT | ERR_FATAL;
5784 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005785 }
5786 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5787 }
5788 else {
5789 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005792 }
5793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794#ifdef TPROXY
5795 else if (!strcmp(args[0], "transparent")) {
5796 /* enable transparent proxy connections */
5797 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005798 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 }
5801#endif
5802 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005803 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005805
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 if (*(args[1]) == 0) {
5807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
5811 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005812 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005815 else if (!strcmp(args[0], "backlog")) { /* backlog */
5816 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005818
5819 if (*(args[1]) == 0) {
5820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005823 }
5824 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005825 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5826 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005827 }
Willy Tarreau86034312006-12-29 00:10:33 +01005828 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005831
Willy Tarreau86034312006-12-29 00:10:33 +01005832 if (*(args[1]) == 0) {
5833 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005836 }
5837 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005838 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5839 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5842 if (*(args[1]) == 0) {
5843 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005847 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5848 if (err) {
5849 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5850 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005851 err_code |= ERR_ALERT | ERR_FATAL;
5852 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005853 }
5854 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005855 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 }
5858 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005859 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005860 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005861 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005862
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 if (curproxy == &defproxy) {
5864 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005868 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005869 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005870
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005871 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005872 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005873 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005875 goto out;
5876 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005877
5878 proto = protocol_by_family(sk->ss_family);
5879 if (!proto || !proto->connect) {
5880 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5881 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
5885
5886 if (port1 != port2) {
5887 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5888 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005892
5893 if (!port1) {
5894 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5895 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005899
William Lallemanddf1425a2015-04-28 20:17:49 +02005900 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5901 goto out;
5902
Willy Tarreaud5191e72010-02-09 20:50:45 +01005903 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005904 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
5906 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005907 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005908 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005909
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005910 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5911 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005916 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005917 /**
5918 * The syntax for hash-type config element is
5919 * hash-type {map-based|consistent} [[<algo>] avalanche]
5920 *
5921 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5922 */
5923 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005924
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005925 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5926 err_code |= ERR_WARN;
5927
5928 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005929 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5930 }
5931 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005932 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5933 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005934 else if (strcmp(args[1], "avalanche") == 0) {
5935 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]);
5936 err_code |= ERR_ALERT | ERR_FATAL;
5937 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005938 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005939 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005940 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005941 err_code |= ERR_ALERT | ERR_FATAL;
5942 goto out;
5943 }
Bhaskar98634f02013-10-29 23:30:51 -04005944
5945 /* set the hash function to use */
5946 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005947 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005948 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005949
5950 /* if consistent with no argument, then avalanche modifier is also applied */
5951 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5952 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005953 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005954 /* set the hash function */
5955 if (!strcmp(args[2], "sdbm")) {
5956 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5957 }
5958 else if (!strcmp(args[2], "djb2")) {
5959 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005960 }
5961 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005962 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005963 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005964 else if (!strcmp(args[2], "crc32")) {
5965 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5966 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005967 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005968 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 -05005969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
5973 /* set the hash modifier */
5974 if (!strcmp(args[3], "avalanche")) {
5975 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5976 }
5977 else if (*args[3]) {
5978 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005982 }
William Lallemanda73203e2012-03-12 12:48:57 +01005983 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005984 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5985 if (*(args[1]) == 0) {
5986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989 }
5990 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5991 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5992 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996 }
William Lallemanda73203e2012-03-12 12:48:57 +01005997 else if (strcmp(args[0], "unique-id-format") == 0) {
5998 if (!*(args[1])) {
5999 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6000 err_code |= ERR_ALERT | ERR_FATAL;
6001 goto out;
6002 }
William Lallemand3203ff42012-11-11 17:30:56 +01006003 if (*(args[2])) {
6004 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006008 free(curproxy->conf.uniqueid_format_string);
6009 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006010
Willy Tarreau62a61232013-04-12 18:13:46 +02006011 free(curproxy->conf.uif_file);
6012 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6013 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006014 }
William Lallemanda73203e2012-03-12 12:48:57 +01006015
6016 else if (strcmp(args[0], "unique-id-header") == 0) {
6017 if (!*(args[1])) {
6018 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6019 err_code |= ERR_ALERT | ERR_FATAL;
6020 goto out;
6021 }
6022 free(curproxy->header_unique_id);
6023 curproxy->header_unique_id = strdup(args[1]);
6024 }
6025
William Lallemand723b73a2012-02-08 16:37:49 +01006026 else if (strcmp(args[0], "log-format") == 0) {
6027 if (!*(args[1])) {
6028 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
William Lallemand3203ff42012-11-11 17:30:56 +01006032 if (*(args[2])) {
6033 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6034 err_code |= ERR_ALERT | ERR_FATAL;
6035 goto out;
6036 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006037 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
6038 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02006039
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02006040 if (curproxy->conf.logformat_string == default_http_log_format)
6041 oldlogformat = "option httplog";
6042 else if (curproxy->conf.logformat_string == default_tcp_log_format)
6043 oldlogformat = "option tcplog";
6044 else if (curproxy->conf.logformat_string == clf_http_log_format)
6045 oldlogformat = "option httplog clf";
6046 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
6047 file, linenum, oldlogformat);
6048 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006049 if (curproxy->conf.logformat_string != default_http_log_format &&
6050 curproxy->conf.logformat_string != default_tcp_log_format &&
6051 curproxy->conf.logformat_string != clf_http_log_format)
6052 free(curproxy->conf.logformat_string);
6053 curproxy->conf.logformat_string = strdup(args[1]);
6054
6055 free(curproxy->conf.lfs_file);
6056 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6057 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006058
6059 /* get a chance to improve log-format error reporting by
6060 * reporting the correct line-number when possible.
6061 */
6062 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6063 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6064 file, linenum, curproxy->id);
6065 err_code |= ERR_WARN;
6066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006068 else if (!strcmp(args[0], "log-format-sd")) {
6069 if (!*(args[1])) {
6070 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
6073 }
6074 if (*(args[2])) {
6075 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
6079
6080 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6081 free(curproxy->conf.logformat_sd_string);
6082 curproxy->conf.logformat_sd_string = strdup(args[1]);
6083
6084 free(curproxy->conf.lfsd_file);
6085 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6086 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6087
6088 /* get a chance to improve log-format-sd error reporting by
6089 * reporting the correct line-number when possible.
6090 */
6091 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6092 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6093 file, linenum, curproxy->id);
6094 err_code |= ERR_WARN;
6095 }
6096 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006097 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6098 if (*(args[1]) == 0) {
6099 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
6102 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006103 chunk_destroy(&curproxy->log_tag);
6104 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006105 }
William Lallemand0f99e342011-10-12 17:50:54 +02006106 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6107 /* delete previous herited or defined syslog servers */
6108 struct logsrv *back;
6109
6110 if (*(args[1]) != 0) {
6111 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
6114 }
6115
William Lallemand723b73a2012-02-08 16:37:49 +01006116 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6117 LIST_DEL(&tmplogsrv->list);
6118 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006119 }
6120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006121 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006122 struct logsrv *logsrv;
6123
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006125 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006126 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006127 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006128 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006129 LIST_INIT(&node->list);
6130 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 }
6133 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006134 struct sockaddr_storage *sk;
6135 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006136 int arg = 0;
6137 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006138
Vincent Bernat02779b62016-04-03 13:48:43 +02006139 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140
Willy Tarreau18324f52014-06-27 18:10:07 +02006141 /* just after the address, a length may be specified */
6142 if (strcmp(args[arg+2], "len") == 0) {
6143 len = atoi(args[arg+3]);
6144 if (len < 80 || len > 65535) {
6145 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6146 file, linenum, args[arg+3]);
6147 err_code |= ERR_ALERT | ERR_FATAL;
6148 goto out;
6149 }
6150 logsrv->maxlen = len;
6151
6152 /* skip these two args */
6153 arg += 2;
6154 }
6155 else
6156 logsrv->maxlen = MAX_SYSLOG_LEN;
6157
Christopher Faulet084aa962017-08-29 16:54:41 +02006158 if (logsrv->maxlen > global.max_syslog_len)
Willy Tarreau18324f52014-06-27 18:10:07 +02006159 global.max_syslog_len = logsrv->maxlen;
Willy Tarreau18324f52014-06-27 18:10:07 +02006160
Dragan Dosen1322d092015-09-22 16:05:32 +02006161 /* after the length, a format may be specified */
6162 if (strcmp(args[arg+2], "format") == 0) {
6163 logsrv->format = get_log_format(args[arg+3]);
6164 if (logsrv->format < 0) {
6165 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6166 err_code |= ERR_ALERT | ERR_FATAL;
6167 goto out;
6168 }
6169
6170 /* skip these two args */
6171 arg += 2;
6172 }
6173
William Lallemanddf1425a2015-04-28 20:17:49 +02006174 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6175 goto out;
6176
Willy Tarreau18324f52014-06-27 18:10:07 +02006177 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006178 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006179 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006180 err_code |= ERR_ALERT | ERR_FATAL;
6181 goto out;
6182
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
6184
William Lallemand0f99e342011-10-12 17:50:54 +02006185 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006186 if (*(args[arg+3])) {
6187 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006188 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006189 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006190 err_code |= ERR_ALERT | ERR_FATAL;
6191 goto out;
6192
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 }
6194 }
6195
William Lallemand0f99e342011-10-12 17:50:54 +02006196 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006197 if (*(args[arg+4])) {
6198 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006199 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006200 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
6203
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006204 }
6205 }
6206
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006207 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006208 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006209 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006210 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006211 goto out;
6212 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006213
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006214 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006215
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006216 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006217 if (port1 != port2) {
6218 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6219 file, linenum, args[0], args[1]);
6220 err_code |= ERR_ALERT | ERR_FATAL;
6221 goto out;
6222 }
6223
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006224 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006225 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006226 }
William Lallemand0f99e342011-10-12 17:50:54 +02006227
6228 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
6230 else {
6231 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6232 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006233 err_code |= ERR_ALERT | ERR_FATAL;
6234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006235 }
6236 }
6237 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006238 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006239 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006240 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006241 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006242
Willy Tarreau977b8e42006-12-29 14:19:17 +01006243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006244 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006245
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006247 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6248 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006252
6253 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006254 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6255 free(curproxy->conn_src.iface_name);
6256 curproxy->conn_src.iface_name = NULL;
6257 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006258
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006259 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006260 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006261 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006262 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006263 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006264 goto out;
6265 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006266
6267 proto = protocol_by_family(sk->ss_family);
6268 if (!proto || !proto->connect) {
6269 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006270 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
6273 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006274
6275 if (port1 != port2) {
6276 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6277 file, linenum, args[0], args[1]);
6278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
6280 }
6281
Willy Tarreauef9a3602012-12-08 22:29:20 +01006282 curproxy->conn_src.source_addr = *sk;
6283 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006284
6285 cur_arg = 2;
6286 while (*(args[cur_arg])) {
6287 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006288#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006289 if (!*args[cur_arg + 1]) {
6290 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6291 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006292 err_code |= ERR_ALERT | ERR_FATAL;
6293 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006294 }
6295
6296 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006297 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6298 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006300 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6301 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006302 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6303 char *name, *end;
6304
6305 name = args[cur_arg+1] + 7;
6306 while (isspace(*name))
6307 name++;
6308
6309 end = name;
6310 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6311 end++;
6312
Willy Tarreauef9a3602012-12-08 22:29:20 +01006313 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6314 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6315 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6316 curproxy->conn_src.bind_hdr_len = end - name;
6317 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6318 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6319 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006320
6321 /* now look for an occurrence number */
6322 while (isspace(*end))
6323 end++;
6324 if (*end == ',') {
6325 end++;
6326 name = end;
6327 if (*end == '-')
6328 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006329 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006330 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006331 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006332 }
6333
Willy Tarreauef9a3602012-12-08 22:29:20 +01006334 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006335 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6336 " occurrences values smaller than %d.\n",
6337 file, linenum, MAX_HDR_HISTORY);
6338 err_code |= ERR_ALERT | ERR_FATAL;
6339 goto out;
6340 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006341 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006342 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006343
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006344 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006345 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006346 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006347 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006348 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006349 goto out;
6350 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006351
6352 proto = protocol_by_family(sk->ss_family);
6353 if (!proto || !proto->connect) {
6354 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6355 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006356 err_code |= ERR_ALERT | ERR_FATAL;
6357 goto out;
6358 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006359
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006360 if (port1 != port2) {
6361 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6362 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006363 err_code |= ERR_ALERT | ERR_FATAL;
6364 goto out;
6365 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006366 curproxy->conn_src.tproxy_addr = *sk;
6367 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006368 }
6369 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006370#else /* no TPROXY support */
6371 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006372 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006373 err_code |= ERR_ALERT | ERR_FATAL;
6374 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006375#endif
6376 cur_arg += 2;
6377 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006378 }
6379
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006380 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6381#ifdef SO_BINDTODEVICE
6382 if (!*args[cur_arg + 1]) {
6383 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6384 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006385 err_code |= ERR_ALERT | ERR_FATAL;
6386 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006387 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006388 free(curproxy->conn_src.iface_name);
6389 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6390 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006391 global.last_checks |= LSTCHK_NETADM;
6392#else
6393 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6394 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006395 err_code |= ERR_ALERT | ERR_FATAL;
6396 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006397#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006398 cur_arg += 2;
6399 continue;
6400 }
6401 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006402 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006407 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6408 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6409 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006410 err_code |= ERR_ALERT | ERR_FATAL;
6411 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6416 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 Tarreauade5ec42010-01-28 19:33:49 +01006420
6421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006422 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006423 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
6434 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
6441 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006442 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006443 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006444 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006445 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
6448 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006449 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006450 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006451 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006452 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006455 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006457 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006458 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006460 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006463 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006466 err_code |= ERR_ALERT | ERR_FATAL;
6467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469
6470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006471 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006472 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 }
6476 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006478 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
6483 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006485 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006489 }
6490 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006492 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006496 }
6497 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006499 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006504 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006506 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006507 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006509 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006512 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006513
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514 if (curproxy == &defproxy) {
6515 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006519 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006520 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 if (*(args[1]) == 0) {
6523 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006524 err_code |= ERR_ALERT | ERR_FATAL;
6525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006527
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006528 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006529 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006530 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6531 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006532 err_code |= ERR_ALERT | ERR_FATAL;
6533 goto out;
6534 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006535 err_code |= warnif_cond_conflicts(cond,
6536 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6537 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006538 }
6539 else if (*args[2]) {
6540 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6541 file, linenum, args[0], args[2]);
6542 err_code |= ERR_ALERT | ERR_FATAL;
6543 goto out;
6544 }
6545
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006546 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006547 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006548 wl->s = strdup(args[1]);
6549 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006550 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 }
6552 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006553 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006554 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006556 err_code |= ERR_ALERT | ERR_FATAL;
6557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006559
Willy Tarreauade5ec42010-01-28 19:33:49 +01006560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006561 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006562 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 }
6566 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006567 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006568 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006569 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006570 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 }
6573 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006574 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006575 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006576 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006577 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 }
6580 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006581 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006584 err_code |= ERR_ALERT | ERR_FATAL;
6585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586 }
6587
Willy Tarreauade5ec42010-01-28 19:33:49 +01006588 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006589 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006590 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006591 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 }
6594 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006595 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006596 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006597 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006598 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 }
6601 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006602 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006603 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006604 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006605 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607 }
6608 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006609 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006610
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 if (curproxy == &defproxy) {
6612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006613 err_code |= ERR_ALERT | ERR_FATAL;
6614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006616 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006617 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006618
Willy Tarreaubaaee002006-06-26 02:48:02 +02006619 if (*(args[1]) == 0) {
6620 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_ALERT | ERR_FATAL;
6622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006623 }
6624
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006625 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Christopher Faulet1b421ea2017-09-22 14:38:56 +02006626 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args+2, &errmsg)) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006627 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6628 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
6631 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006632 err_code |= warnif_cond_conflicts(cond,
6633 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6634 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006635 }
6636 else if (*args[2]) {
6637 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6638 file, linenum, args[0], args[2]);
6639 err_code |= ERR_ALERT | ERR_FATAL;
6640 goto out;
6641 }
6642
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006643 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006644 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006645 wl->s = strdup(args[1]);
6646 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 }
6648 else if (!strcmp(args[0], "errorloc") ||
6649 !strcmp(args[0], "errorloc302") ||
6650 !strcmp(args[0], "errorloc303")) { /* error location */
6651 int errnum, errlen;
6652 char *err;
6653
Willy Tarreau977b8e42006-12-29 14:19:17 +01006654 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006656
Willy Tarreaubaaee002006-06-26 02:48:02 +02006657 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006658 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006659 err_code |= ERR_ALERT | ERR_FATAL;
6660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006661 }
6662
6663 errnum = atol(args[1]);
6664 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006665 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6666 err = malloc(errlen);
6667 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006668 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006669 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6670 err = malloc(errlen);
6671 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006672 }
6673
Willy Tarreau0f772532006-12-23 20:51:41 +01006674 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6675 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006676 chunk_destroy(&curproxy->errmsg[rc]);
6677 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006678 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006681
6682 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006683 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6684 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006685 free(err);
6686 }
6687 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006688 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6689 int errnum, errlen, fd;
6690 char *err;
6691 struct stat stat;
6692
6693 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006694 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006695
6696 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006697 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006698 err_code |= ERR_ALERT | ERR_FATAL;
6699 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006700 }
6701
6702 fd = open(args[2], O_RDONLY);
6703 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6704 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6705 file, linenum, args[2], args[1]);
6706 if (fd >= 0)
6707 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006708 err_code |= ERR_ALERT | ERR_FATAL;
6709 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006710 }
6711
Willy Tarreau27a674e2009-08-17 07:23:33 +02006712 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006713 errlen = stat.st_size;
6714 } else {
6715 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006716 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006717 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006718 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006719 }
6720
6721 err = malloc(errlen); /* malloc() must succeed during parsing */
6722 errnum = read(fd, err, errlen);
6723 if (errnum != errlen) {
6724 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6725 file, linenum, args[2], args[1]);
6726 close(fd);
6727 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006728 err_code |= ERR_ALERT | ERR_FATAL;
6729 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006730 }
6731 close(fd);
6732
6733 errnum = atol(args[1]);
6734 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6735 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006736 chunk_destroy(&curproxy->errmsg[rc]);
6737 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006738 break;
6739 }
6740 }
6741
6742 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006743 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6744 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006745 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006746 free(err);
6747 }
6748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006749 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006750 struct cfg_kw_list *kwl;
6751 int index;
6752
6753 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6754 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6755 if (kwl->kw[index].section != CFG_LISTEN)
6756 continue;
6757 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6758 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006759 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006760 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006761 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006764 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006765 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006766 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006767 err_code |= ERR_WARN;
6768 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006769 }
Willy Tarreau93893792009-07-23 13:19:11 +02006770 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006771 }
6772 }
6773 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006774
Willy Tarreau6daf3432008-01-22 16:44:08 +01006775 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006776 err_code |= ERR_ALERT | ERR_FATAL;
6777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006778 }
Willy Tarreau93893792009-07-23 13:19:11 +02006779 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006780 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006781 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006782}
6783
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006784int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006785cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6786{
6787#ifdef CONFIG_HAP_NS
6788 const char *err;
6789 const char *item = args[0];
6790
6791 if (!strcmp(item, "namespace_list")) {
6792 return 0;
6793 }
6794 else if (!strcmp(item, "namespace")) {
6795 size_t idx = 1;
6796 const char *current;
6797 while (*(current = args[idx++])) {
6798 err = invalid_char(current);
6799 if (err) {
6800 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6801 file, linenum, *err, item, current);
6802 return ERR_ALERT | ERR_FATAL;
6803 }
6804
6805 if (netns_store_lookup(current, strlen(current))) {
6806 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6807 file, linenum, current);
6808 return ERR_ALERT | ERR_FATAL;
6809 }
6810 if (!netns_store_insert(current)) {
6811 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6812 file, linenum, current);
6813 return ERR_ALERT | ERR_FATAL;
6814 }
6815 }
6816 }
6817
6818 return 0;
6819#else
6820 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6821 file, linenum);
6822 return ERR_ALERT | ERR_FATAL;
6823#endif
6824}
6825
6826int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006827cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6828{
6829
6830 int err_code = 0;
6831 const char *err;
6832
6833 if (!strcmp(args[0], "userlist")) { /* new userlist */
6834 struct userlist *newul;
6835
6836 if (!*args[1]) {
6837 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6838 file, linenum, args[0]);
6839 err_code |= ERR_ALERT | ERR_FATAL;
6840 goto out;
6841 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6843 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844
6845 err = invalid_char(args[1]);
6846 if (err) {
6847 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6848 file, linenum, *err, args[0], args[1]);
6849 err_code |= ERR_ALERT | ERR_FATAL;
6850 goto out;
6851 }
6852
6853 for (newul = userlist; newul; newul = newul->next)
6854 if (!strcmp(newul->name, args[1])) {
6855 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6856 file, linenum, args[1]);
6857 err_code |= ERR_WARN;
6858 goto out;
6859 }
6860
Vincent Bernat02779b62016-04-03 13:48:43 +02006861 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 if (!newul) {
6863 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6864 err_code |= ERR_ALERT | ERR_ABORT;
6865 goto out;
6866 }
6867
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006869 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6871 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006872 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006873 goto out;
6874 }
6875
6876 newul->next = userlist;
6877 userlist = newul;
6878
6879 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006880 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006881 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006882 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006883
6884 if (!*args[1]) {
6885 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6886 file, linenum, args[0]);
6887 err_code |= ERR_ALERT | ERR_FATAL;
6888 goto out;
6889 }
6890
6891 err = invalid_char(args[1]);
6892 if (err) {
6893 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6894 file, linenum, *err, args[0], args[1]);
6895 err_code |= ERR_ALERT | ERR_FATAL;
6896 goto out;
6897 }
6898
William Lallemand4ac9f542015-05-28 18:03:51 +02006899 if (!userlist)
6900 goto out;
6901
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006902 for (ag = userlist->groups; ag; ag = ag->next)
6903 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006904 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6905 file, linenum, args[1], userlist->name);
6906 err_code |= ERR_ALERT;
6907 goto out;
6908 }
6909
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006910 ag = calloc(1, sizeof(*ag));
6911 if (!ag) {
6912 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6913 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006914 goto out;
6915 }
6916
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006917 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006918 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006919 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6920 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006921 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006922 goto out;
6923 }
6924
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006925 cur_arg = 2;
6926
6927 while (*args[cur_arg]) {
6928 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006929 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006930 cur_arg += 2;
6931 continue;
6932 } else {
6933 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6934 file, linenum, args[0]);
6935 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006936 free(ag->groupusers);
6937 free(ag->name);
6938 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006939 goto out;
6940 }
6941 }
6942
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006943 ag->next = userlist->groups;
6944 userlist->groups = ag;
6945
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006946 } else if (!strcmp(args[0], "user")) { /* new user */
6947 struct auth_users *newuser;
6948 int cur_arg;
6949
6950 if (!*args[1]) {
6951 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6952 file, linenum, args[0]);
6953 err_code |= ERR_ALERT | ERR_FATAL;
6954 goto out;
6955 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006956 if (!userlist)
6957 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006958
6959 for (newuser = userlist->users; newuser; newuser = newuser->next)
6960 if (!strcmp(newuser->user, args[1])) {
6961 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6962 file, linenum, args[1], userlist->name);
6963 err_code |= ERR_ALERT;
6964 goto out;
6965 }
6966
Vincent Bernat02779b62016-04-03 13:48:43 +02006967 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006968 if (!newuser) {
6969 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6970 err_code |= ERR_ALERT | ERR_ABORT;
6971 goto out;
6972 }
6973
6974 newuser->user = strdup(args[1]);
6975
6976 newuser->next = userlist->users;
6977 userlist->users = newuser;
6978
6979 cur_arg = 2;
6980
6981 while (*args[cur_arg]) {
6982 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006983#ifdef CONFIG_HAP_CRYPT
6984 if (!crypt("", args[cur_arg + 1])) {
6985 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6986 file, linenum, newuser->user);
6987 err_code |= ERR_ALERT | ERR_FATAL;
6988 goto out;
6989 }
6990#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006991 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6992 file, linenum);
6993 err_code |= ERR_ALERT;
6994#endif
6995 newuser->pass = strdup(args[cur_arg + 1]);
6996 cur_arg += 2;
6997 continue;
6998 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6999 newuser->pass = strdup(args[cur_arg + 1]);
7000 newuser->flags |= AU_O_INSECURE;
7001 cur_arg += 2;
7002 continue;
7003 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007004 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007005 cur_arg += 2;
7006 continue;
7007 } else {
7008 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7009 file, linenum, args[0]);
7010 err_code |= ERR_ALERT | ERR_FATAL;
7011 goto out;
7012 }
7013 }
7014 } else {
7015 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7016 err_code |= ERR_ALERT | ERR_FATAL;
7017 }
7018
7019out:
7020 return err_code;
7021}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007022
Christopher Faulet79bdef32016-11-04 22:36:15 +01007023int
7024cfg_parse_scope(const char *file, int linenum, char *line)
7025{
7026 char *beg, *end, *scope = NULL;
7027 int err_code = 0;
7028 const char *err;
7029
7030 beg = line + 1;
7031 end = strchr(beg, ']');
7032
7033 /* Detect end of scope declaration */
7034 if (!end || end == beg) {
7035 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7036 file, linenum);
7037 err_code |= ERR_ALERT | ERR_FATAL;
7038 goto out;
7039 }
7040
7041 /* Get scope name and check its validity */
7042 scope = my_strndup(beg, end-beg);
7043 err = invalid_char(scope);
7044 if (err) {
7045 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7046 file, linenum, *err);
7047 err_code |= ERR_ALERT | ERR_ABORT;
7048 goto out;
7049 }
7050
7051 /* Be sure to have a scope declaration alone on its line */
7052 line = end+1;
7053 while (isspace((unsigned char)*line))
7054 line++;
7055 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7056 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7057 file, linenum, *line);
7058 err_code |= ERR_ALERT | ERR_ABORT;
7059 goto out;
7060 }
7061
7062 /* We have a valid scope declaration, save it */
7063 free(cfg_scope);
7064 cfg_scope = scope;
7065 scope = NULL;
7066
7067 out:
7068 free(scope);
7069 return err_code;
7070}
7071
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072/*
7073 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007074 * Returns the error code, 0 if OK, or any combination of :
7075 * - ERR_ABORT: must abort ASAP
7076 * - ERR_FATAL: we can continue parsing but not start the service
7077 * - ERR_WARN: a warning has been emitted
7078 * - ERR_ALERT: an alert has been emitted
7079 * Only the two first ones can stop processing, the two others are just
7080 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007081 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007082int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083{
William Lallemand64e84512015-05-12 14:25:37 +02007084 char *thisline;
7085 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007086 FILE *f;
7087 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007088 int err_code = 0;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007089 struct cfg_section *cs = NULL, *pcs = NULL;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007090 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007091 int readbytes = 0;
7092
7093 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007094 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007095 return -1;
7096 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007097
David Carlier97880bb2016-04-08 10:35:26 +01007098 if ((f=fopen(file,"r")) == NULL) {
7099 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102
William Lallemandb2f07452015-05-12 14:27:13 +02007103next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007104 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007105 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007106 char *end;
7107 char *args[MAX_LINE_ARGS + 1];
7108 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007109 int dquote = 0; /* double quote */
7110 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007111
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 linenum++;
7113
7114 end = line + strlen(line);
7115
William Lallemand64e84512015-05-12 14:25:37 +02007116 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007117 /* Check if we reached the limit and the last char is not \n.
7118 * Watch out for the last line without the terminating '\n'!
7119 */
William Lallemand64e84512015-05-12 14:25:37 +02007120 char *newline;
7121 int newlinesize = linesize * 2;
7122
7123 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7124 if (newline == NULL) {
7125 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7126 file, linenum);
7127 err_code |= ERR_ALERT | ERR_FATAL;
7128 continue;
7129 }
7130
7131 readbytes = linesize - 1;
7132 linesize = newlinesize;
7133 thisline = newline;
7134 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007135 }
7136
William Lallemand64e84512015-05-12 14:25:37 +02007137 readbytes = 0;
7138
Willy Tarreaubaaee002006-06-26 02:48:02 +02007139 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007140 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007141 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007142
Christopher Faulet79bdef32016-11-04 22:36:15 +01007143
7144 if (*line == '[') {/* This is the begining if a scope */
7145 err_code |= cfg_parse_scope(file, linenum, line);
7146 goto next_line;
7147 }
7148
Willy Tarreaubaaee002006-06-26 02:48:02 +02007149 arg = 0;
7150 args[arg] = line;
7151
7152 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007153 if (*line == '"' && !squote) { /* double quote outside single quotes */
7154 if (dquote)
7155 dquote = 0;
7156 else
7157 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007158 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007159 end--;
7160 }
7161 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7162 if (squote)
7163 squote = 0;
7164 else
7165 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007166 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007167 end--;
7168 }
7169 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007170 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7171 * C equivalent value. Other combinations left unchanged (eg: \1).
7172 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007173 int skip = 0;
7174 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7175 *line = line[1];
7176 skip = 1;
7177 }
7178 else if (line[1] == 'r') {
7179 *line = '\r';
7180 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007182 else if (line[1] == 'n') {
7183 *line = '\n';
7184 skip = 1;
7185 }
7186 else if (line[1] == 't') {
7187 *line = '\t';
7188 skip = 1;
7189 }
7190 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007191 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007192 unsigned char hex1, hex2;
7193 hex1 = toupper(line[2]) - '0';
7194 hex2 = toupper(line[3]) - '0';
7195 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7196 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7197 *line = (hex1<<4) + hex2;
7198 skip = 3;
7199 }
7200 else {
7201 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007203 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007204 } else if (line[1] == '"') {
7205 *line = '"';
7206 skip = 1;
7207 } else if (line[1] == '\'') {
7208 *line = '\'';
7209 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007210 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7211 *line = '$';
7212 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007213 }
7214 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007215 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216 end -= skip;
7217 }
7218 line++;
7219 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007220 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007221 /* end of string, end of loop */
7222 *line = 0;
7223 break;
7224 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007225 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007227 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007228 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007229 line++;
7230 args[++arg] = line;
7231 }
William Lallemandb2f07452015-05-12 14:27:13 +02007232 else if (dquote && *line == '$') {
7233 /* environment variables are evaluated inside double quotes */
7234 char *var_beg;
7235 char *var_end;
7236 char save_char;
7237 char *value;
7238 int val_len;
7239 int newlinesize;
7240 int braces = 0;
7241
7242 var_beg = line + 1;
7243 var_end = var_beg;
7244
7245 if (*var_beg == '{') {
7246 var_beg++;
7247 var_end++;
7248 braces = 1;
7249 }
7250
7251 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7252 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7253 err_code |= ERR_ALERT | ERR_FATAL;
7254 goto next_line; /* skip current line */
7255 }
7256
7257 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7258 var_end++;
7259
7260 save_char = *var_end;
7261 *var_end = '\0';
7262 value = getenv(var_beg);
7263 *var_end = save_char;
7264 val_len = value ? strlen(value) : 0;
7265
7266 if (braces) {
7267 if (*var_end == '}') {
7268 var_end++;
7269 braces = 0;
7270 } else {
7271 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7272 err_code |= ERR_ALERT | ERR_FATAL;
7273 goto next_line; /* skip current line */
7274 }
7275 }
7276
7277 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7278
7279 /* if not enough space in thisline */
7280 if (newlinesize > linesize) {
7281 char *newline;
7282
7283 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7284 if (newline == NULL) {
7285 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7286 err_code |= ERR_ALERT | ERR_FATAL;
7287 goto next_line; /* slip current line */
7288 }
7289 /* recompute pointers if realloc returns a new pointer */
7290 if (newline != thisline) {
7291 int i;
7292 int diff;
7293
7294 for (i = 0; i <= arg; i++) {
7295 diff = args[i] - thisline;
7296 args[i] = newline + diff;
7297 }
7298
7299 diff = var_end - thisline;
7300 var_end = newline + diff;
7301 diff = end - thisline;
7302 end = newline + diff;
7303 diff = line - thisline;
7304 line = newline + diff;
7305 thisline = newline;
7306 }
7307 linesize = newlinesize;
7308 }
7309
7310 /* insert value inside the line */
7311 memmove(line + val_len, var_end, end - var_end + 1);
7312 memcpy(line, value, val_len);
7313 end += val_len - (var_end - line);
7314 line += val_len;
7315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007316 else {
7317 line++;
7318 }
7319 }
William Lallemandb2f07452015-05-12 14:27:13 +02007320
William Lallemandf9873ba2015-05-05 17:37:14 +02007321 if (dquote) {
7322 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7323 err_code |= ERR_ALERT | ERR_FATAL;
7324 }
7325
7326 if (squote) {
7327 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7328 err_code |= ERR_ALERT | ERR_FATAL;
7329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007330
7331 /* empty line */
7332 if (!**args)
7333 continue;
7334
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007335 if (*line) {
7336 /* we had to stop due to too many args.
7337 * Let's terminate the string, print the offending part then cut the
7338 * last arg.
7339 */
7340 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7341 line++;
7342 *line = '\0';
7343
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007344 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007345 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007346 err_code |= ERR_ALERT | ERR_FATAL;
7347 args[arg] = line;
7348 }
7349
Willy Tarreau540abe42007-05-02 20:50:16 +02007350 /* zero out remaining args and ensure that at least one entry
7351 * is zeroed out.
7352 */
7353 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007354 args[arg] = line;
7355 }
7356
Willy Tarreau3842f002009-06-14 11:39:52 +02007357 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007358 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007359 char *tmp;
7360
Willy Tarreau3842f002009-06-14 11:39:52 +02007361 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007362 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007363 for (arg=0; *args[arg+1]; arg++)
7364 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007365 *tmp = '\0'; // fix the next arg to \0
7366 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007367 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007368 else if (!strcmp(args[0], "default")) {
7369 kwm = KWM_DEF;
7370 for (arg=0; *args[arg+1]; arg++)
7371 args[arg] = args[arg+1]; // shift args after inversion
7372 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007373
William Lallemand0f99e342011-10-12 17:50:54 +02007374 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7375 strcmp(args[0], "log") != 0) {
7376 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007377 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007378 }
7379
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007380 /* detect section start */
7381 list_for_each_entry(ics, &sections, list) {
7382 if (strcmp(args[0], ics->section_name) == 0) {
7383 cursection = ics->section_name;
7384 cs = ics;
7385 break;
7386 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007387 }
7388
William Lallemandd2ff56d2017-10-16 11:06:50 +02007389 if (!cs) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007390 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007391 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemandd2ff56d2017-10-16 11:06:50 +02007392 } else {
7393 /* else it's a section keyword */
Willy Tarreau058e9072009-07-20 09:30:05 +02007394
William Lallemandd2ff56d2017-10-16 11:06:50 +02007395 if (pcs != cs && pcs && pcs->post_section_parser) {
7396 err_code |= pcs->post_section_parser();
7397 if (err_code & ERR_ABORT)
7398 goto err;
7399 }
7400
7401 err_code |= cs->section_parser(file, linenum, args, kwm);
7402 if (err_code & ERR_ABORT)
7403 goto err;
7404 }
7405 pcs = cs;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007406 }
William Lallemandd2ff56d2017-10-16 11:06:50 +02007407
7408 if (pcs == cs && pcs && pcs->post_section_parser)
7409 err_code |= pcs->post_section_parser();
7410
7411err:
Christopher Faulet79bdef32016-11-04 22:36:15 +01007412 free(cfg_scope);
7413 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007414 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007415 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007416 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007417 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007418}
7419
Willy Tarreau64ab6072014-09-16 12:17:36 +02007420/* This function propagates processes from frontend <from> to backend <to> so
7421 * that it is always guaranteed that a backend pointed to by a frontend is
7422 * bound to all of its processes. After that, if the target is a "listen"
7423 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007424 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007425 * checked first to ensure that <to> is already bound to all processes of
7426 * <from>, there is no risk of looping and we ensure to follow the shortest
7427 * path to the destination.
7428 *
7429 * It is possible to set <to> to NULL for the first call so that the function
7430 * takes care of visiting the initial frontend in <from>.
7431 *
7432 * It is important to note that the function relies on the fact that all names
7433 * have already been resolved.
7434 */
7435void propagate_processes(struct proxy *from, struct proxy *to)
7436{
7437 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007438
7439 if (to) {
7440 /* check whether we need to go down */
7441 if (from->bind_proc &&
7442 (from->bind_proc & to->bind_proc) == from->bind_proc)
7443 return;
7444
7445 if (!from->bind_proc && !to->bind_proc)
7446 return;
7447
7448 to->bind_proc = from->bind_proc ?
7449 (to->bind_proc | from->bind_proc) : 0;
7450
7451 /* now propagate down */
7452 from = to;
7453 }
7454
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007455 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007456 return;
7457
Willy Tarreauf6b70012014-12-18 14:00:43 +01007458 if (from->state == PR_STSTOPPED)
7459 return;
7460
Willy Tarreau64ab6072014-09-16 12:17:36 +02007461 /* default_backend */
7462 if (from->defbe.be)
7463 propagate_processes(from, from->defbe.be);
7464
7465 /* use_backend */
7466 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007467 if (rule->dynamic)
7468 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007469 to = rule->be.backend;
7470 propagate_processes(from, to);
7471 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007472}
7473
Willy Tarreaubb925012009-07-23 13:36:36 +02007474/*
7475 * Returns the error code, 0 if OK, or any combination of :
7476 * - ERR_ABORT: must abort ASAP
7477 * - ERR_FATAL: we can continue parsing but not start the service
7478 * - ERR_WARN: a warning has been emitted
7479 * - ERR_ALERT: an alert has been emitted
7480 * Only the two first ones can stop processing, the two others are just
7481 * indicators.
7482 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007483int check_config_validity()
7484{
7485 int cfgerr = 0;
7486 struct proxy *curproxy = NULL;
7487 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007488 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007489 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007490 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007491 char *err;
William Lallemand48b4bb42017-10-23 14:36:34 +02007492 struct cfg_postparser *postparser;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007493
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007494 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495 /*
7496 * Now, check for the integrity of all that we have collected.
7497 */
7498
7499 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007500 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007501
Willy Tarreau193b8c62012-11-22 00:17:38 +01007502 if (!global.tune.max_http_hdr)
7503 global.tune.max_http_hdr = MAX_HTTP_HDR;
7504
7505 if (!global.tune.cookie_len)
7506 global.tune.cookie_len = CAPTURE_LEN;
7507
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007508 if (!global.tune.requri_len)
7509 global.tune.requri_len = REQURI_LEN;
7510
Emeric Brun96fd9262017-07-05 13:33:16 +02007511 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7512
Willy Tarreau193b8c62012-11-22 00:17:38 +01007513 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7514
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007515 /* Post initialisation of the users and groups lists. */
7516 err_code = userlist_postinit();
7517 if (err_code != ERR_NONE)
7518 goto out;
7519
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007520 /* first, we will invert the proxy list order */
7521 curproxy = NULL;
7522 while (proxy) {
7523 struct proxy *next;
7524
7525 next = proxy->next;
7526 proxy->next = curproxy;
7527 curproxy = proxy;
7528 if (!next)
7529 break;
7530 proxy = next;
7531 }
7532
Willy Tarreau419ead82014-09-16 13:41:21 +02007533 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007534 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007535 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007536 struct sticking_rule *mrule;
Christopher Faulete4e830d2017-09-18 14:51:41 +02007537 struct act_rule *arule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007538 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007539 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007540 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007541
Willy Tarreau050536d2012-10-04 08:47:34 +02007542 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007543 /* proxy ID not set, use automatic numbering with first
7544 * spare entry starting with next_pxid.
7545 */
7546 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7547 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7548 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007549 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007550 next_pxid++;
7551
Willy Tarreau55ea7572007-06-17 19:56:27 +02007552
Willy Tarreaubaaee002006-06-26 02:48:02 +02007553 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007554 /* ensure we don't keep listeners uselessly bound */
7555 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007556 free((void *)curproxy->table.peers.name);
7557 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007558 continue;
7559 }
7560
Willy Tarreau102df612014-05-07 23:56:38 +02007561 /* Check multi-process mode compatibility for the current proxy */
7562
7563 if (curproxy->bind_proc) {
7564 /* an explicit bind-process was specified, let's check how many
7565 * processes remain.
7566 */
David Carliere6c39412015-07-02 07:00:17 +00007567 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007568
7569 curproxy->bind_proc &= nbits(global.nbproc);
7570 if (!curproxy->bind_proc && nbproc == 1) {
7571 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);
7572 curproxy->bind_proc = 1;
7573 }
7574 else if (!curproxy->bind_proc && nbproc > 1) {
7575 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);
7576 curproxy->bind_proc = 0;
7577 }
7578 }
7579
Willy Tarreau3d209582014-05-09 17:06:11 +02007580 /* check and reduce the bind-proc of each listener */
7581 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7582 unsigned long mask;
7583
7584 if (!bind_conf->bind_proc)
7585 continue;
7586
7587 mask = nbits(global.nbproc);
7588 if (curproxy->bind_proc)
7589 mask &= curproxy->bind_proc;
7590 /* mask cannot be null here thanks to the previous checks */
7591
David Carliere6c39412015-07-02 07:00:17 +00007592 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007593 bind_conf->bind_proc &= mask;
7594
7595 if (!bind_conf->bind_proc && nbproc == 1) {
7596 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",
7597 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7598 bind_conf->bind_proc = mask & ~(mask - 1);
7599 }
7600 else if (!bind_conf->bind_proc && nbproc > 1) {
7601 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",
7602 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7603 bind_conf->bind_proc = 0;
7604 }
7605 }
7606
Willy Tarreauff01a212009-03-15 13:46:16 +01007607 switch (curproxy->mode) {
7608 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007609 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007610 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007611 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007613 cfgerr++;
7614 }
7615
7616 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007617 Warning("config : servers will be ignored for %s '%s'.\n",
7618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007619 break;
7620
7621 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007622 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007623 break;
7624
7625 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007626 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007627 break;
7628 }
7629
Willy Tarreauf3934b82015-08-11 11:36:45 +02007630 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7631 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7632 proxy_type_str(curproxy), curproxy->id);
7633 err_code |= ERR_WARN;
7634 }
7635
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007636 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007637 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007638 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007639 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7640 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007641 cfgerr++;
7642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007643#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007644 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007645 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7646 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007647 cfgerr++;
7648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007649#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007650 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007651 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7652 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007653 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007654 }
7655 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007656 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007657 /* If no LB algo is set in a backend, and we're not in
7658 * transparent mode, dispatch mode nor proxy mode, we
7659 * want to use balance roundrobin by default.
7660 */
7661 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7662 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007663 }
7664 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007665
Willy Tarreau1620ec32011-08-06 17:05:02 +02007666 if (curproxy->options & PR_O_DISPATCH)
7667 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7668 else if (curproxy->options & PR_O_HTTP_PROXY)
7669 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7670 else if (curproxy->options & PR_O_TRANSP)
7671 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007672
Willy Tarreau1620ec32011-08-06 17:05:02 +02007673 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7674 if (curproxy->options & PR_O_DISABLE404) {
7675 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7676 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7677 err_code |= ERR_WARN;
7678 curproxy->options &= ~PR_O_DISABLE404;
7679 }
7680 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7681 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7682 "send-state", proxy_type_str(curproxy), curproxy->id);
7683 err_code |= ERR_WARN;
7684 curproxy->options &= ~PR_O2_CHK_SNDST;
7685 }
Willy Tarreauef781042010-01-27 11:53:01 +01007686 }
7687
Simon Horman98637e52014-06-20 12:30:16 +09007688 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7689 if (!global.external_check) {
7690 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7691 curproxy->id, "option external-check");
7692 cfgerr++;
7693 }
7694 if (!curproxy->check_command) {
7695 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7696 curproxy->id, "option external-check");
7697 cfgerr++;
7698 }
7699 }
7700
Simon Horman64e34162015-02-06 11:11:57 +09007701 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007702 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7703 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007704 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7705 "'email-alert myhostname', or 'email-alert to' "
7706 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007707 "to be present).\n",
7708 proxy_type_str(curproxy), curproxy->id);
7709 err_code |= ERR_WARN;
7710 free_email_alert(curproxy);
7711 }
7712 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007713 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007714 }
7715
Simon Horman98637e52014-06-20 12:30:16 +09007716 if (curproxy->check_command) {
7717 int clear = 0;
7718 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7719 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7720 "external-check command", proxy_type_str(curproxy), curproxy->id);
7721 err_code |= ERR_WARN;
7722 clear = 1;
7723 }
7724 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007725 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007726 curproxy->id, "external-check command");
7727 cfgerr++;
7728 }
7729 if (clear) {
7730 free(curproxy->check_command);
7731 curproxy->check_command = NULL;
7732 }
7733 }
7734
7735 if (curproxy->check_path) {
7736 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7737 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7738 "external-check path", proxy_type_str(curproxy), curproxy->id);
7739 err_code |= ERR_WARN;
7740 free(curproxy->check_path);
7741 curproxy->check_path = NULL;
7742 }
7743 }
7744
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007745 /* if a default backend was specified, let's find it */
7746 if (curproxy->defbe.name) {
7747 struct proxy *target;
7748
Willy Tarreauafb39922015-05-26 12:04:09 +02007749 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007750 if (!target) {
7751 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7752 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007753 cfgerr++;
7754 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007755 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7756 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007757 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007758 } else if (target->mode != curproxy->mode &&
7759 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7760
7761 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7762 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7763 curproxy->conf.file, curproxy->conf.line,
7764 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7765 target->conf.file, target->conf.line);
7766 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007767 } else {
7768 free(curproxy->defbe.name);
7769 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007770 /* Update tot_fe_maxconn for a further fullconn's computation */
7771 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007772 /* Emit a warning if this proxy also has some servers */
7773 if (curproxy->srv) {
7774 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7775 curproxy->id);
7776 err_code |= ERR_WARN;
7777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007778 }
7779 }
7780
Emeric Brun3f783572017-01-12 11:21:28 +01007781 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7782 /* Case of listen without default backend
7783 * The curproxy will be its own default backend
7784 * so we update tot_fe_maxconn for a further
7785 * fullconn's computation */
7786 curproxy->tot_fe_maxconn += curproxy->maxconn;
7787 }
7788
Willy Tarreau55ea7572007-06-17 19:56:27 +02007789 /* find the target proxy for 'use_backend' rules */
7790 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007791 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007792 struct logformat_node *node;
7793 char *pxname;
7794
7795 /* Try to parse the string as a log format expression. If the result
7796 * of the parsing is only one entry containing a simple string, then
7797 * it's a standard string corresponding to a static rule, thus the
7798 * parsing is cancelled and be.name is restored to be resolved.
7799 */
7800 pxname = rule->be.name;
7801 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007802 curproxy->conf.args.ctx = ARGC_UBK;
7803 curproxy->conf.args.file = rule->file;
7804 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007805 err = NULL;
7806 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7807 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7808 rule->file, rule->line, pxname, err);
7809 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007810 cfgerr++;
7811 continue;
7812 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007813 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7814
7815 if (!LIST_ISEMPTY(&rule->be.expr)) {
7816 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7817 rule->dynamic = 1;
7818 free(pxname);
7819 continue;
7820 }
7821 /* simple string: free the expression and fall back to static rule */
7822 free(node->arg);
7823 free(node);
7824 }
7825
7826 rule->dynamic = 0;
7827 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007828
Willy Tarreauafb39922015-05-26 12:04:09 +02007829 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007830 if (!target) {
7831 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7832 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007833 cfgerr++;
7834 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007835 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7836 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007837 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007838 } else if (target->mode != curproxy->mode &&
7839 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7840
7841 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7842 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7843 curproxy->conf.file, curproxy->conf.line,
7844 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7845 target->conf.file, target->conf.line);
7846 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007847 } else {
7848 free((void *)rule->be.name);
7849 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007850 /* For each target of switching rules, we update
7851 * their tot_fe_maxconn, except if a previous rule point
7852 * on the same backend or on the default backend */
7853 if (rule->be.backend != curproxy->defbe.be) {
7854 struct switching_rule *swrule;
7855
7856 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7857 if (rule == swrule) {
7858 target->tot_fe_maxconn += curproxy->maxconn;
7859 break;
7860 }
7861 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7862 /* there is multiple ref of this backend */
7863 break;
7864 }
7865 }
7866 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007867 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007868 }
7869
Willy Tarreau64ab6072014-09-16 12:17:36 +02007870 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007871 list_for_each_entry(srule, &curproxy->server_rules, list) {
7872 struct server *target = findserver(curproxy, srule->srv.name);
7873
7874 if (!target) {
7875 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7876 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7877 cfgerr++;
7878 continue;
7879 }
7880 free((void *)srule->srv.name);
7881 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007882 }
7883
Emeric Brunb982a3d2010-01-04 15:45:53 +01007884 /* find the target table for 'stick' rules */
7885 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7886 struct proxy *target;
7887
Emeric Brun1d33b292010-01-04 15:47:17 +01007888 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7889 if (mrule->flags & STK_IS_STORE)
7890 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7891
Emeric Brunb982a3d2010-01-04 15:45:53 +01007892 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007893 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007894 else
7895 target = curproxy;
7896
7897 if (!target) {
7898 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7899 curproxy->id, mrule->table.name);
7900 cfgerr++;
7901 }
7902 else if (target->table.size == 0) {
7903 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7904 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7905 cfgerr++;
7906 }
Willy Tarreau12785782012-04-27 21:37:17 +02007907 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7908 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007909 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7910 cfgerr++;
7911 }
7912 else {
7913 free((void *)mrule->table.name);
7914 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007915 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007916 }
7917 }
7918
7919 /* find the target table for 'store response' rules */
7920 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7921 struct proxy *target;
7922
Emeric Brun1d33b292010-01-04 15:47:17 +01007923 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7924
Emeric Brunb982a3d2010-01-04 15:45:53 +01007925 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007926 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007927 else
7928 target = curproxy;
7929
7930 if (!target) {
7931 Alert("Proxy '%s': unable to find store table '%s'.\n",
7932 curproxy->id, mrule->table.name);
7933 cfgerr++;
7934 }
7935 else if (target->table.size == 0) {
7936 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7937 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7938 cfgerr++;
7939 }
Willy Tarreau12785782012-04-27 21:37:17 +02007940 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7941 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007942 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7943 cfgerr++;
7944 }
7945 else {
7946 free((void *)mrule->table.name);
7947 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007948 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007949 }
7950 }
7951
Christopher Faulete4e830d2017-09-18 14:51:41 +02007952 /* check validity for 'tcp-request' layer 4 rules */
7953 list_for_each_entry(arule, &curproxy->tcp_req.l4_rules, list) {
7954 err = NULL;
7955 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7956 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7957 free(err);
Willy Tarreau5f53de72012-12-12 00:25:44 +01007958 cfgerr++;
7959 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007960 }
7961
Christopher Faulete4e830d2017-09-18 14:51:41 +02007962 /* check validity for 'tcp-request' layer 5 rules */
7963 list_for_each_entry(arule, &curproxy->tcp_req.l5_rules, list) {
7964 err = NULL;
7965 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7966 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7967 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007968 cfgerr++;
7969 }
7970 }
7971
Christopher Faulete4e830d2017-09-18 14:51:41 +02007972 /* check validity for 'tcp-request' layer 6 rules */
7973 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
7974 err = NULL;
7975 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7976 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7977 free(err);
Baptiste Assmanne9544932015-11-03 23:31:35 +01007978 cfgerr++;
7979 }
7980 }
7981
Christopher Faulete4e830d2017-09-18 14:51:41 +02007982 /* check validity for 'http-request' layer 7 rules */
7983 list_for_each_entry(arule, &curproxy->http_req_rules, list) {
7984 err = NULL;
7985 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7986 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7987 free(err);
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007988 cfgerr++;
7989 }
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007990 }
7991
Christopher Faulete4e830d2017-09-18 14:51:41 +02007992 /* check validity for 'http-response' layer 7 rules */
7993 list_for_each_entry(arule, &curproxy->http_res_rules, list) {
7994 err = NULL;
7995 if (arule->check_ptr && !arule->check_ptr(arule, curproxy, &err)) {
7996 Alert("Proxy '%s': %s.\n", curproxy->id, err);
7997 free(err);
Willy Tarreau09448f72014-06-25 18:12:15 +02007998 cfgerr++;
7999 }
Willy Tarreau09448f72014-06-25 18:12:15 +02008000 }
8001
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008002 /* move any "block" rules at the beginning of the http-request rules */
8003 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8004 /* insert block_rules into http_req_rules at the beginning */
8005 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8006 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8007 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8008 curproxy->http_req_rules.n = curproxy->block_rules.n;
8009 LIST_INIT(&curproxy->block_rules);
8010 }
8011
Emeric Brun32da3c42010-09-23 18:39:19 +02008012 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008013 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008014
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008015 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008016 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8017 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008018 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008019 break;
8020 }
8021 }
8022
8023 if (!curpeers) {
8024 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8025 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008026 free((void *)curproxy->table.peers.name);
8027 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008028 cfgerr++;
8029 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008030 else if (curpeers->state == PR_STSTOPPED) {
8031 /* silently disable this peers section */
8032 curproxy->table.peers.p = NULL;
8033 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008034 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008035 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8036 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008037 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008038 cfgerr++;
8039 }
8040 }
8041
Simon Horman9dc49962015-01-30 11:22:59 +09008042
8043 if (curproxy->email_alert.mailers.name) {
8044 struct mailers *curmailers = mailers;
8045
8046 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
Christopher Faulet0108bb32017-10-20 21:34:32 +02008047 if (!strcmp(curmailers->id, curproxy->email_alert.mailers.name))
Simon Horman9dc49962015-01-30 11:22:59 +09008048 break;
Simon Horman9dc49962015-01-30 11:22:59 +09008049 }
Simon Horman9dc49962015-01-30 11:22:59 +09008050 if (!curmailers) {
8051 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8052 curproxy->id, curproxy->email_alert.mailers.name);
8053 free_email_alert(curproxy);
8054 cfgerr++;
8055 }
Christopher Faulet0108bb32017-10-20 21:34:32 +02008056 else {
8057 err = NULL;
8058 if (init_email_alert(curmailers, curproxy, &err)) {
8059 Alert("Proxy '%s': %s.\n", curproxy->id, err);
8060 free(err);
8061 cfgerr++;
8062 }
8063 }
Simon Horman9dc49962015-01-30 11:22:59 +09008064 }
8065
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008066 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008067 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008068 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8069 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8070 "proxy", curproxy->id);
8071 cfgerr++;
8072 goto out_uri_auth_compat;
8073 }
8074
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008075 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008076 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008077 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008078 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008079
Willy Tarreau95fa4692010-02-01 13:05:50 +01008080 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8081 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008082
8083 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008084 uri_auth_compat_req[i++] = "realm";
8085 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8086 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008087
Willy Tarreau95fa4692010-02-01 13:05:50 +01008088 uri_auth_compat_req[i++] = "unless";
8089 uri_auth_compat_req[i++] = "{";
8090 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8091 uri_auth_compat_req[i++] = "}";
8092 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008093
Willy Tarreauff011f22011-01-06 17:51:27 +01008094 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8095 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008096 cfgerr++;
8097 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008098 }
8099
Willy Tarreauff011f22011-01-06 17:51:27 +01008100 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008101
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008102 if (curproxy->uri_auth->auth_realm) {
8103 free(curproxy->uri_auth->auth_realm);
8104 curproxy->uri_auth->auth_realm = NULL;
8105 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008106
8107 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008108 }
8109out_uri_auth_compat:
8110
Dragan Dosen43885c72015-10-01 13:18:13 +02008111 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008112 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008113 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8114 if (!curproxy->conf.logformat_sd_string) {
8115 /* set the default logformat_sd_string */
8116 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8117 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008118 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008119 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008120 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008121
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008122 /* compile the log format */
8123 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008124 if (curproxy->conf.logformat_string != default_http_log_format &&
8125 curproxy->conf.logformat_string != default_tcp_log_format &&
8126 curproxy->conf.logformat_string != clf_http_log_format)
8127 free(curproxy->conf.logformat_string);
8128 curproxy->conf.logformat_string = NULL;
8129 free(curproxy->conf.lfs_file);
8130 curproxy->conf.lfs_file = NULL;
8131 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008132
8133 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8134 free(curproxy->conf.logformat_sd_string);
8135 curproxy->conf.logformat_sd_string = NULL;
8136 free(curproxy->conf.lfsd_file);
8137 curproxy->conf.lfsd_file = NULL;
8138 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008139 }
8140
Willy Tarreau62a61232013-04-12 18:13:46 +02008141 if (curproxy->conf.logformat_string) {
8142 curproxy->conf.args.ctx = ARGC_LOG;
8143 curproxy->conf.args.file = curproxy->conf.lfs_file;
8144 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008145 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008146 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008147 SMP_VAL_FE_LOG_END, &err)) {
8148 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8149 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8150 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008151 cfgerr++;
8152 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008153 curproxy->conf.args.file = NULL;
8154 curproxy->conf.args.line = 0;
8155 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008156
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008157 if (curproxy->conf.logformat_sd_string) {
8158 curproxy->conf.args.ctx = ARGC_LOGSD;
8159 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8160 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008161 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008162 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 +01008163 SMP_VAL_FE_LOG_END, &err)) {
8164 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8165 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8166 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008167 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008168 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8169 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8170 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8171 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008172 cfgerr++;
8173 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008174 curproxy->conf.args.file = NULL;
8175 curproxy->conf.args.line = 0;
8176 }
8177
Willy Tarreau62a61232013-04-12 18:13:46 +02008178 if (curproxy->conf.uniqueid_format_string) {
8179 curproxy->conf.args.ctx = ARGC_UIF;
8180 curproxy->conf.args.file = curproxy->conf.uif_file;
8181 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008182 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008183 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 +01008184 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8185 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8186 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8187 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008188 cfgerr++;
8189 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008190 curproxy->conf.args.file = NULL;
8191 curproxy->conf.args.line = 0;
8192 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008193
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008194 /* only now we can check if some args remain unresolved.
8195 * This must be done after the users and groups resolution.
8196 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008197 cfgerr += smp_resolve_args(curproxy);
8198 if (!cfgerr)
8199 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008200
Willy Tarreau2738a142006-07-08 17:28:09 +02008201 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008202 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008203 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008204 (!curproxy->timeout.connect ||
8205 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008206 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008207 " | While not properly invalid, you will certainly encounter various problems\n"
8208 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008209 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008210 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008211 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008212 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008213
Willy Tarreau1fa31262007-12-03 00:36:16 +01008214 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8215 * We must still support older configurations, so let's find out whether those
8216 * parameters have been set or must be copied from contimeouts.
8217 */
8218 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008219 if (!curproxy->timeout.tarpit ||
8220 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008221 /* tarpit timeout not set. We search in the following order:
8222 * default.tarpit, curr.connect, default.connect.
8223 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008224 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008225 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008226 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008227 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008228 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008229 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008230 }
8231 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008232 (!curproxy->timeout.queue ||
8233 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008234 /* queue timeout not set. We search in the following order:
8235 * default.queue, curr.connect, default.connect.
8236 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008237 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008238 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008239 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008240 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008241 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008242 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008243 }
8244 }
8245
Willy Tarreau1620ec32011-08-06 17:05:02 +02008246 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008247 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008248 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008249 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008250 }
8251
Willy Tarreau215663d2014-06-13 18:30:23 +02008252 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8253 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8254 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8255 proxy_type_str(curproxy), curproxy->id);
8256 err_code |= ERR_WARN;
8257 }
8258
Willy Tarreau193b8c62012-11-22 00:17:38 +01008259 /* ensure that cookie capture length is not too large */
8260 if (curproxy->capture_len >= global.tune.cookie_len) {
8261 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8262 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8263 err_code |= ERR_WARN;
8264 curproxy->capture_len = global.tune.cookie_len - 1;
8265 }
8266
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008267 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008268 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008269 curproxy->req_cap_pool = create_pool("ptrcap",
8270 curproxy->nb_req_cap * sizeof(char *),
8271 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008272 }
8273
8274 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008275 curproxy->rsp_cap_pool = create_pool("ptrcap",
8276 curproxy->nb_rsp_cap * sizeof(char *),
8277 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008278 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008279
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008280 switch (curproxy->load_server_state_from_file) {
8281 case PR_SRV_STATE_FILE_UNSPEC:
8282 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8283 break;
8284 case PR_SRV_STATE_FILE_GLOBAL:
8285 if (!global.server_state_file) {
8286 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",
8287 curproxy->id);
8288 err_code |= ERR_WARN;
8289 }
8290 break;
8291 }
8292
Willy Tarreaubaaee002006-06-26 02:48:02 +02008293 /* first, we will invert the servers list order */
8294 newsrv = NULL;
8295 while (curproxy->srv) {
8296 struct server *next;
8297
8298 next = curproxy->srv->next;
8299 curproxy->srv->next = newsrv;
8300 newsrv = curproxy->srv;
8301 if (!next)
8302 break;
8303 curproxy->srv = next;
8304 }
8305
Willy Tarreau17edc812014-01-03 12:14:34 +01008306 /* Check that no server name conflicts. This causes trouble in the stats.
8307 * We only emit a warning for the first conflict affecting each server,
8308 * in order to avoid combinatory explosion if all servers have the same
8309 * name. We do that only for servers which do not have an explicit ID,
8310 * because these IDs were made also for distinguishing them and we don't
8311 * want to annoy people who correctly manage them.
8312 */
8313 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8314 struct server *other_srv;
8315
8316 if (newsrv->puid)
8317 continue;
8318
8319 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8320 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8321 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8322 newsrv->conf.file, newsrv->conf.line,
8323 proxy_type_str(curproxy), curproxy->id,
8324 newsrv->id, other_srv->conf.line);
8325 break;
8326 }
8327 }
8328 }
8329
Willy Tarreaudd701652010-05-25 23:03:02 +02008330 /* assign automatic UIDs to servers which don't have one yet */
8331 next_id = 1;
8332 newsrv = curproxy->srv;
8333 while (newsrv != NULL) {
8334 if (!newsrv->puid) {
8335 /* server ID not set, use automatic numbering with first
8336 * spare entry starting with next_svid.
8337 */
8338 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8339 newsrv->conf.id.key = newsrv->puid = next_id;
8340 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8341 }
8342 next_id++;
8343 newsrv = newsrv->next;
8344 }
8345
Willy Tarreau20697042007-11-15 23:26:18 +01008346 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008347 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008348
Willy Tarreau62c3be22012-01-20 13:12:32 +01008349 /*
8350 * If this server supports a maxconn parameter, it needs a dedicated
8351 * tasks to fill the emptied slots when a connection leaves.
8352 * Also, resolve deferred tracking dependency if needed.
8353 */
8354 newsrv = curproxy->srv;
8355 while (newsrv != NULL) {
8356 if (newsrv->minconn > newsrv->maxconn) {
8357 /* Only 'minconn' was specified, or it was higher than or equal
8358 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8359 * this will avoid further useless expensive computations.
8360 */
8361 newsrv->maxconn = newsrv->minconn;
8362 } else if (newsrv->maxconn && !newsrv->minconn) {
8363 /* minconn was not specified, so we set it to maxconn */
8364 newsrv->minconn = newsrv->maxconn;
8365 }
8366
Willy Tarreau17d45382016-12-22 21:16:08 +01008367 /* this will also properly set the transport layer for prod and checks */
8368 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8369 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8370 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8371 }
Emeric Brun94324a42012-10-11 14:00:19 +02008372
Willy Tarreau2f075e92013-12-03 11:11:34 +01008373 /* set the check type on the server */
8374 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8375
Willy Tarreau62c3be22012-01-20 13:12:32 +01008376 if (newsrv->trackit) {
8377 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008378 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008379 char *pname, *sname;
8380
8381 pname = newsrv->trackit;
8382 sname = strrchr(pname, '/');
8383
8384 if (sname)
8385 *sname++ = '\0';
8386 else {
8387 sname = pname;
8388 pname = NULL;
8389 }
8390
8391 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008392 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008393 if (!px) {
8394 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8395 proxy_type_str(curproxy), curproxy->id,
8396 newsrv->id, pname);
8397 cfgerr++;
8398 goto next_srv;
8399 }
8400 } else
8401 px = curproxy;
8402
8403 srv = findserver(px, sname);
8404 if (!srv) {
8405 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8406 proxy_type_str(curproxy), curproxy->id,
8407 newsrv->id, sname);
8408 cfgerr++;
8409 goto next_srv;
8410 }
8411
Willy Tarreau32091232014-05-16 13:52:00 +02008412 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8413 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8414 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008415 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008416 "tracking as it does not have any check nor agent enabled.\n",
8417 proxy_type_str(curproxy), curproxy->id,
8418 newsrv->id, px->id, srv->id);
8419 cfgerr++;
8420 goto next_srv;
8421 }
8422
8423 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8424
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008425 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008426 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8427 "belongs to a tracking chain looping back to %s/%s.\n",
8428 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008429 newsrv->id, px->id, srv->id, px->id,
8430 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008431 cfgerr++;
8432 goto next_srv;
8433 }
8434
8435 if (curproxy != px &&
8436 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8437 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8438 "tracking: disable-on-404 option inconsistency.\n",
8439 proxy_type_str(curproxy), curproxy->id,
8440 newsrv->id, px->id, srv->id);
8441 cfgerr++;
8442 goto next_srv;
8443 }
8444
Willy Tarreau62c3be22012-01-20 13:12:32 +01008445 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008446 newsrv->tracknext = srv->trackers;
8447 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008448
8449 free(newsrv->trackit);
8450 newsrv->trackit = NULL;
8451 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008452
Willy Tarreau62c3be22012-01-20 13:12:32 +01008453 next_srv:
8454 newsrv = newsrv->next;
8455 }
8456
Olivier Houchard4e694042017-03-14 20:01:29 +01008457 /*
8458 * Try to generate dynamic cookies for servers now.
8459 * It couldn't be done earlier, since at the time we parsed
8460 * the server line, we may not have known yet that we
8461 * should use dynamic cookies, or the secret key may not
8462 * have been provided yet.
8463 */
8464 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8465 newsrv = curproxy->srv;
8466 while (newsrv != NULL) {
8467 srv_set_dyncookie(newsrv);
8468 newsrv = newsrv->next;
8469 }
8470
8471 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008472 /* We have to initialize the server lookup mechanism depending
8473 * on what LB algorithm was choosen.
8474 */
8475
8476 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8477 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8478 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008479 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8480 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8481 init_server_map(curproxy);
8482 } else {
8483 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8484 fwrr_init_server_groups(curproxy);
8485 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008486 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008487
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008488 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008489 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8490 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8491 fwlc_init_server_tree(curproxy);
8492 } else {
8493 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8494 fas_init_server_tree(curproxy);
8495 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008496 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008497
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008498 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008499 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8500 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8501 chash_init_server_tree(curproxy);
8502 } else {
8503 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8504 init_server_map(curproxy);
8505 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008506 break;
8507 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01008508 HA_SPIN_INIT(&curproxy->lbprm.lock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02008509
8510 if (curproxy->options & PR_O_LOGASAP)
8511 curproxy->to_log &= ~LW_BYTES;
8512
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008513 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008514 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8515 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008516 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8517 proxy_type_str(curproxy), curproxy->id);
8518 err_code |= ERR_WARN;
8519 }
8520
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008521 if (curproxy->mode != PR_MODE_HTTP) {
8522 int optnum;
8523
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008524 if (curproxy->uri_auth) {
8525 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8526 proxy_type_str(curproxy), curproxy->id);
8527 err_code |= ERR_WARN;
8528 curproxy->uri_auth = NULL;
8529 }
8530
Willy Tarreaude7dc882017-03-10 11:49:21 +01008531 if (curproxy->capture_name) {
8532 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8533 proxy_type_str(curproxy), curproxy->id);
8534 err_code |= ERR_WARN;
8535 }
8536
8537 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8538 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8539 proxy_type_str(curproxy), curproxy->id);
8540 err_code |= ERR_WARN;
8541 }
8542
8543 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8544 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8545 proxy_type_str(curproxy), curproxy->id);
8546 err_code |= ERR_WARN;
8547 }
8548
8549 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8550 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8551 proxy_type_str(curproxy), curproxy->id);
8552 err_code |= ERR_WARN;
8553 }
8554
8555 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8556 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8557 proxy_type_str(curproxy), curproxy->id);
8558 err_code |= ERR_WARN;
8559 }
8560
Willy Tarreau87cf5142011-08-19 22:57:24 +02008561 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008562 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8563 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8564 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008565 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008566 }
8567
8568 if (curproxy->options & PR_O_ORGTO) {
8569 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8570 "originalto", proxy_type_str(curproxy), curproxy->id);
8571 err_code |= ERR_WARN;
8572 curproxy->options &= ~PR_O_ORGTO;
8573 }
8574
8575 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8576 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8577 (curproxy->cap & cfg_opts[optnum].cap) &&
8578 (curproxy->options & cfg_opts[optnum].val)) {
8579 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8580 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8581 err_code |= ERR_WARN;
8582 curproxy->options &= ~cfg_opts[optnum].val;
8583 }
8584 }
8585
8586 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8587 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8588 (curproxy->cap & cfg_opts2[optnum].cap) &&
8589 (curproxy->options2 & cfg_opts2[optnum].val)) {
8590 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8591 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8592 err_code |= ERR_WARN;
8593 curproxy->options2 &= ~cfg_opts2[optnum].val;
8594 }
8595 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008596
Willy Tarreau29fbe512015-08-20 19:35:14 +02008597#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008598 if (curproxy->conn_src.bind_hdr_occ) {
8599 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008600 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008601 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008602 err_code |= ERR_WARN;
8603 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008604#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008605 }
8606
Willy Tarreaubaaee002006-06-26 02:48:02 +02008607 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008608 * ensure that we're not cross-dressing a TCP server into HTTP.
8609 */
8610 newsrv = curproxy->srv;
8611 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008612 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008613 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8614 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008615 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008616 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008617
Willy Tarreau0cec3312011-10-31 13:49:26 +01008618 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8619 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8620 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8621 err_code |= ERR_WARN;
8622 }
8623
Willy Tarreauc93cd162014-05-13 15:54:22 +02008624 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008625 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8626 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8627 err_code |= ERR_WARN;
8628 }
8629
Willy Tarreau29fbe512015-08-20 19:35:14 +02008630#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008631 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8632 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008633 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 +01008634 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008635 err_code |= ERR_WARN;
8636 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008637#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008638
8639 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8640 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8641 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8642 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8643 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8644 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",
8645 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8646 err_code |= ERR_WARN;
8647 }
8648
8649
8650 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8651 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",
8652 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8653 err_code |= ERR_WARN;
8654 }
8655 }
8656
Willy Tarreau21d2af32008-02-14 20:25:24 +01008657 newsrv = newsrv->next;
8658 }
8659
Willy Tarreaue42bd962014-09-16 16:21:19 +02008660 /* check if we have a frontend with "tcp-request content" looking at L7
8661 * with no inspect-delay
8662 */
8663 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
Christopher Faulete4e830d2017-09-18 14:51:41 +02008664 list_for_each_entry(arule, &curproxy->tcp_req.inspect_rules, list) {
8665 if (arule->action == ACT_TCP_CAPTURE &&
8666 !(arule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008667 break;
Christopher Faulete4e830d2017-09-18 14:51:41 +02008668 if ((arule->action >= ACT_ACTION_TRK_SC0 && arule->action <= ACT_ACTION_TRK_SCMAX) &&
8669 !(arule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008670 break;
8671 }
8672
Christopher Faulete4e830d2017-09-18 14:51:41 +02008673 if (&arule->list != &curproxy->tcp_req.inspect_rules) {
Willy Tarreaue42bd962014-09-16 16:21:19 +02008674 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8675 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8676 " This means that these rules will randomly find their contents. This can be fixed by"
8677 " setting the tcp-request inspect-delay.\n",
8678 proxy_type_str(curproxy), curproxy->id);
8679 err_code |= ERR_WARN;
8680 }
8681 }
8682
Christopher Fauletd7c91962015-04-30 11:48:27 +02008683 /* Check filter configuration, if any */
8684 cfgerr += flt_check(curproxy);
8685
Willy Tarreauc1a21672009-08-16 22:37:44 +02008686 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008687 if (!curproxy->accept)
8688 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008689
Willy Tarreauc1a21672009-08-16 22:37:44 +02008690 if (curproxy->tcp_req.inspect_delay ||
8691 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008692 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008693
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008694 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008695 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008696 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008697 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008698
8699 /* both TCP and HTTP must check switching rules */
8700 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008701
8702 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008703 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008704 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8705 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 +01008706 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008707 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8708 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008709 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008710 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008711 }
8712
8713 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008714 if (curproxy->tcp_req.inspect_delay ||
8715 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8716 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8717
Emeric Brun97679e72010-09-23 17:56:44 +02008718 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8719 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8720
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008721 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008722 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008723 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008724 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008725
8726 /* If the backend does requires RDP cookie persistence, we have to
8727 * enable the corresponding analyser.
8728 */
8729 if (curproxy->options2 & PR_O2_RDPC_PRST)
8730 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008731
8732 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008733 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008734 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8735 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 +01008736 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008737 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8738 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008739 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008740 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008741 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008742 }
8743
8744 /***********************************************************/
8745 /* At this point, target names have already been resolved. */
8746 /***********************************************************/
8747
8748 /* Check multi-process mode compatibility */
8749
8750 if (global.nbproc > 1 && global.stats_fe) {
8751 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8752 unsigned long mask;
8753
8754 mask = nbits(global.nbproc);
8755 if (global.stats_fe->bind_proc)
8756 mask &= global.stats_fe->bind_proc;
8757
8758 if (bind_conf->bind_proc)
8759 mask &= bind_conf->bind_proc;
8760
8761 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008762 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008763 break;
8764 }
8765 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8766 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");
8767 }
8768 }
8769
8770 /* Make each frontend inherit bind-process from its listeners when not specified. */
8771 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8772 if (curproxy->bind_proc)
8773 continue;
8774
8775 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8776 unsigned long mask;
8777
Willy Tarreaue428b082015-05-04 21:57:58 +02008778 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008779 curproxy->bind_proc |= mask;
8780 }
8781
8782 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008783 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008784 }
8785
8786 if (global.stats_fe) {
8787 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8788 unsigned long mask;
8789
Cyril Bonté06181952016-02-24 00:14:54 +01008790 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008791 global.stats_fe->bind_proc |= mask;
8792 }
8793 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008794 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008795 }
8796
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008797 /* propagate bindings from frontends to backends. Don't do it if there
8798 * are any fatal errors as we must not call it with unresolved proxies.
8799 */
8800 if (!cfgerr) {
8801 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8802 if (curproxy->cap & PR_CAP_FE)
8803 propagate_processes(curproxy, NULL);
8804 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008805 }
8806
8807 /* Bind each unbound backend to all processes when not specified. */
8808 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8809 if (curproxy->bind_proc)
8810 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008811 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008812 }
8813
8814 /*******************************************************/
8815 /* At this step, all proxies have a non-null bind_proc */
8816 /*******************************************************/
8817
8818 /* perform the final checks before creating tasks */
8819
8820 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8821 struct listener *listener;
8822 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008823
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008824 /* Configure SSL for each bind line.
8825 * Note: if configuration fails at some point, the ->ctx member
8826 * remains NULL so that listeners can later detach.
8827 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008828 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008829 if (bind_conf->xprt->prepare_bind_conf &&
8830 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008831 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008832 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008833
Willy Tarreaue6b98942007-10-29 01:09:36 +01008834 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008835 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008836 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008837 int nbproc;
8838
8839 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008840 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008841 nbits(global.nbproc));
8842
8843 if (!nbproc) /* no intersection between listener and frontend */
8844 nbproc = 1;
8845
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008846 if (!listener->luid) {
8847 /* listener ID not set, use automatic numbering with first
8848 * spare entry starting with next_luid.
8849 */
8850 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8851 listener->conf.id.key = listener->luid = next_id;
8852 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008853 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008854 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008855
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008856 /* enable separate counters */
8857 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008858 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008859 if (!listener->name)
8860 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008861 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008862
Willy Tarreaue6b98942007-10-29 01:09:36 +01008863 if (curproxy->options & PR_O_TCP_NOLING)
8864 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008865 if (!listener->maxconn)
8866 listener->maxconn = curproxy->maxconn;
8867 if (!listener->backlog)
8868 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008869 if (!listener->maxaccept)
8870 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8871
8872 /* we want to have an optimal behaviour on single process mode to
8873 * maximize the work at once, but in multi-process we want to keep
8874 * some fairness between processes, so we target half of the max
8875 * number of events to be balanced over all the processes the proxy
8876 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8877 * used to disable the limit.
8878 */
8879 if (listener->maxaccept > 0) {
8880 if (nbproc > 1)
8881 listener->maxaccept = (listener->maxaccept + 1) / 2;
8882 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8883 }
8884
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008885 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008886 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008887 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008888
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008889 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008890 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008891
Willy Tarreau620408f2016-10-21 16:37:51 +02008892 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8893 listener->options |= LI_O_TCP_L5_RULES;
8894
Willy Tarreaude3041d2010-05-31 10:56:17 +02008895 if (curproxy->mon_mask.s_addr)
8896 listener->options |= LI_O_CHK_MONNET;
8897
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008898 /* smart accept mode is automatic in HTTP mode */
8899 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008900 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008901 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8902 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008903 }
8904
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008905 /* Release unused SSL configs */
8906 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008907 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8908 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008909 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008910
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008911 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008912 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008913 int count, maxproc = 0;
8914
8915 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008916 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008917 if (count > maxproc)
8918 maxproc = count;
8919 }
8920 /* backends have 0, frontends have 1 or more */
8921 if (maxproc != 1)
8922 Warning("Proxy '%s': in multi-process mode, stats will be"
8923 " limited to process assigned to the current request.\n",
8924 curproxy->id);
8925
Willy Tarreau102df612014-05-07 23:56:38 +02008926 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8927 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8928 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008929 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008930 }
Willy Tarreau102df612014-05-07 23:56:38 +02008931 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8932 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8933 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008934 }
8935 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008936
8937 /* create the task associated with the proxy */
Emeric Brunc60def82017-09-27 14:59:38 +02008938 curproxy->task = task_new(MAX_THREADS_MASK);
Willy Tarreau918ff602011-07-25 16:33:49 +02008939 if (curproxy->task) {
8940 curproxy->task->context = curproxy;
8941 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02008942 } else {
8943 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8944 curproxy->id);
8945 cfgerr++;
8946 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008947 }
8948
Willy Tarreaufbb78422011-06-05 15:38:35 +02008949 /* automatically compute fullconn if not set. We must not do it in the
8950 * loop above because cross-references are not yet fully resolved.
8951 */
8952 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8953 /* If <fullconn> is not set, let's set it to 10% of the sum of
8954 * the possible incoming frontend's maxconns.
8955 */
8956 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008957 /* we have the sum of the maxconns in <total>. We only
8958 * keep 10% of that sum to set the default fullconn, with
8959 * a hard minimum of 1 (to avoid a divide by zero).
8960 */
Emeric Brun3f783572017-01-12 11:21:28 +01008961 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008962 if (!curproxy->fullconn)
8963 curproxy->fullconn = 1;
8964 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008965 }
8966
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008967 /*
8968 * Recount currently required checks.
8969 */
8970
8971 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8972 int optnum;
8973
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008974 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8975 if (curproxy->options & cfg_opts[optnum].val)
8976 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008977
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008978 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8979 if (curproxy->options2 & cfg_opts2[optnum].val)
8980 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008981 }
8982
Willy Tarreau0fca4832015-05-01 19:12:05 +02008983 /* compute the required process bindings for the peers */
8984 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8985 if (curproxy->table.peers.p)
8986 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8987
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008988 if (cfg_peers) {
8989 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02008990 struct peer *p, *pb;
8991
Willy Tarreau1e273012015-05-01 19:15:17 +02008992 /* Remove all peers sections which don't have a valid listener,
8993 * which are not used by any table, or which are bound to more
8994 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008995 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008996 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02008997 while (*last) {
8998 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008999
9000 if (curpeers->state == PR_STSTOPPED) {
9001 /* the "disabled" keyword was present */
9002 if (curpeers->peers_fe)
9003 stop_proxy(curpeers->peers_fe);
9004 curpeers->peers_fe = NULL;
9005 }
9006 else if (!curpeers->peers_fe) {
9007 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9008 curpeers->id, localpeer);
9009 }
David Carliere6c39412015-07-02 07:00:17 +00009010 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009011 /* either it's totally stopped or too much used */
9012 if (curpeers->peers_fe->bind_proc) {
9013 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009014 "running in different processes (%d different ones). "
9015 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009016 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009017 cfgerr++;
9018 }
9019 stop_proxy(curpeers->peers_fe);
9020 curpeers->peers_fe = NULL;
9021 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009022 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009023 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009024 last = &curpeers->next;
9025 continue;
9026 }
9027
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009028 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009029 p = curpeers->remote;
9030 while (p) {
9031 pb = p->next;
9032 free(p->id);
9033 free(p);
9034 p = pb;
9035 }
9036
9037 /* Destroy and unlink this curpeers section.
9038 * Note: curpeers is backed up into *last.
9039 */
9040 free(curpeers->id);
9041 curpeers = curpeers->next;
9042 free(*last);
9043 *last = curpeers;
9044 }
9045 }
9046
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009047 /* initialize stick-tables on backend capable proxies. This must not
9048 * be done earlier because the data size may be discovered while parsing
9049 * other proxies.
9050 */
9051 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9052 if (curproxy->state == PR_STSTOPPED)
9053 continue;
9054
9055 if (!stktable_init(&curproxy->table)) {
9056 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9057 cfgerr++;
9058 }
9059 }
9060
Simon Horman0d16a402015-01-30 11:22:58 +09009061 if (mailers) {
9062 struct mailers *curmailers = mailers, **last;
9063 struct mailer *m, *mb;
9064
9065 /* Remove all mailers sections which don't have a valid listener.
9066 * This can happen when a mailers section is never referenced.
9067 */
9068 last = &mailers;
9069 while (*last) {
9070 curmailers = *last;
9071 if (curmailers->users) {
9072 last = &curmailers->next;
9073 continue;
9074 }
9075
9076 Warning("Removing incomplete section 'mailers %s'.\n",
9077 curmailers->id);
9078
9079 m = curmailers->mailer_list;
9080 while (m) {
9081 mb = m->next;
9082 free(m->id);
9083 free(m);
9084 m = mb;
9085 }
9086
9087 /* Destroy and unlink this curmailers section.
9088 * Note: curmailers is backed up into *last.
9089 */
9090 free(curmailers->id);
9091 curmailers = curmailers->next;
9092 free(*last);
9093 *last = curmailers;
9094 }
9095 }
9096
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009097 /* Update server_state_file_name to backend name if backend is supposed to use
9098 * a server-state file locally defined and none has been provided */
9099 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9100 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9101 curproxy->server_state_file_name == NULL)
9102 curproxy->server_state_file_name = strdup(curproxy->id);
9103 }
9104
Willy Tarreau34eb6712011-10-24 18:15:04 +02009105 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009106 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009107 MEM_F_SHARED);
9108
William Lallemand48b4bb42017-10-23 14:36:34 +02009109 list_for_each_entry(postparser, &postparsers, list) {
9110 if (postparser->func)
9111 cfgerr += postparser->func();
9112 }
9113
Willy Tarreaubb925012009-07-23 13:36:36 +02009114 if (cfgerr > 0)
9115 err_code |= ERR_ALERT | ERR_FATAL;
9116 out:
9117 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009118}
9119
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009120/*
9121 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9122 * parsing sessions.
9123 */
9124void cfg_register_keywords(struct cfg_kw_list *kwl)
9125{
9126 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9127}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009128
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009129/*
9130 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9131 */
9132void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9133{
9134 LIST_DEL(&kwl->list);
9135 LIST_INIT(&kwl->list);
9136}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009137
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009138/* this function register new section in the haproxy configuration file.
9139 * <section_name> is the name of this new section and <section_parser>
9140 * is the called parser. If two section declaration have the same name,
9141 * only the first declared is used.
9142 */
9143int cfg_register_section(char *section_name,
William Lallemandd2ff56d2017-10-16 11:06:50 +02009144 int (*section_parser)(const char *, int, char **, int),
9145 int (*post_section_parser)())
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009146{
9147 struct cfg_section *cs;
9148
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009149 list_for_each_entry(cs, &sections, list) {
9150 if (strcmp(cs->section_name, section_name) == 0) {
9151 Alert("register section '%s': already registered.\n", section_name);
9152 return 0;
9153 }
9154 }
9155
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009156 cs = calloc(1, sizeof(*cs));
9157 if (!cs) {
9158 Alert("register section '%s': out of memory.\n", section_name);
9159 return 0;
9160 }
9161
9162 cs->section_name = section_name;
9163 cs->section_parser = section_parser;
William Lallemandd2ff56d2017-10-16 11:06:50 +02009164 cs->post_section_parser = post_section_parser;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009165
9166 LIST_ADDQ(&sections, &cs->list);
9167
9168 return 1;
9169}
9170
William Lallemand48b4bb42017-10-23 14:36:34 +02009171/* this function register a new function which will be called once the haproxy
9172 * configuration file has been parsed. It's useful to check dependencies
9173 * between sections or to resolve items once everything is parsed.
9174 */
9175int cfg_register_postparser(char *name, int (*func)())
9176{
9177 struct cfg_postparser *cp;
9178
9179 cp = calloc(1, sizeof(*cp));
9180 if (!cp) {
9181 Alert("register postparser '%s': out of memory.\n", name);
9182 return 0;
9183 }
9184 cp->name = name;
9185 cp->func = func;
9186
9187 LIST_ADDQ(&postparsers, &cp->list);
9188
9189 return 1;
9190}
9191
Willy Tarreaubaaee002006-06-26 02:48:02 +02009192/*
David Carlier845efb52015-09-25 11:49:18 +01009193 * free all config section entries
9194 */
9195void cfg_unregister_sections(void)
9196{
9197 struct cfg_section *cs, *ics;
9198
9199 list_for_each_entry_safe(cs, ics, &sections, list) {
9200 LIST_DEL(&cs->list);
9201 free(cs);
9202 }
9203}
9204
Christopher Faulet7110b402016-10-26 11:09:44 +02009205void cfg_backup_sections(struct list *backup_sections)
9206{
9207 struct cfg_section *cs, *ics;
9208
9209 list_for_each_entry_safe(cs, ics, &sections, list) {
9210 LIST_DEL(&cs->list);
9211 LIST_ADDQ(backup_sections, &cs->list);
9212 }
9213}
9214
9215void cfg_restore_sections(struct list *backup_sections)
9216{
9217 struct cfg_section *cs, *ics;
9218
9219 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9220 LIST_DEL(&cs->list);
9221 LIST_ADDQ(&sections, &cs->list);
9222 }
9223}
9224
Willy Tarreau659fbf02016-05-26 17:55:28 +02009225__attribute__((constructor))
9226static void cfgparse_init(void)
9227{
9228 /* Register internal sections */
William Lallemandd2ff56d2017-10-16 11:06:50 +02009229 cfg_register_section("listen", cfg_parse_listen, NULL);
9230 cfg_register_section("frontend", cfg_parse_listen, NULL);
9231 cfg_register_section("backend", cfg_parse_listen, NULL);
9232 cfg_register_section("defaults", cfg_parse_listen, NULL);
9233 cfg_register_section("global", cfg_parse_global, NULL);
9234 cfg_register_section("userlist", cfg_parse_users, NULL);
9235 cfg_register_section("peers", cfg_parse_peers, NULL);
9236 cfg_register_section("mailers", cfg_parse_mailers, NULL);
9237 cfg_register_section("namespace_list", cfg_parse_netns, NULL);
9238 cfg_register_section("resolvers", cfg_parse_resolvers, NULL);
Willy Tarreau659fbf02016-05-26 17:55:28 +02009239}
9240
David Carlier845efb52015-09-25 11:49:18 +01009241/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009242 * Local variables:
9243 * c-indent-level: 8
9244 * c-basic-offset: 8
9245 * End:
9246 */