blob: ec8f6a1f08a0e4b7cc49e7cfa7378a629ceeca17 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020083#include <proto/raw_sock.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
Emeric Brunfc0421f2012-09-07 17:30:07 +020088#ifdef USE_OPENSSL
89#include <types/ssl_sock.h>
90#include <proto/ssl_sock.h>
91#include <proto/shctx.h>
92#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020093
Willy Tarreauf3c69202006-07-09 16:42:34 +020094/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
95 * ssl-hello-chk option to ensure that the remote server speaks SSL.
96 *
97 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
98 */
99const char sslv3_client_hello_pkt[] = {
100 "\x16" /* ContentType : 0x16 = Hanshake */
101 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
102 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
103 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
104 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
105 "\x03\x00" /* Hello Version : 0x0300 = v3 */
106 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
107 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
108 "\x00" /* Session ID length : empty (no session ID) */
109 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
110 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
111 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
112 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
113 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
114 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
115 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
116 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
117 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
118 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
119 "\x00\x38" "\x00\x39" "\x00\x3A"
120 "\x01" /* Compression Length : 0x01 = 1 byte for types */
121 "\x00" /* Compression Type : 0x00 = NULL compression */
122};
123
Willy Tarreau3842f002009-06-14 11:39:52 +0200124/* various keyword modifiers */
125enum kw_mod {
126 KWM_STD = 0, /* normal */
127 KWM_NO, /* "no" prefixed before the keyword */
128 KWM_DEF, /* "default" prefixed before the keyword */
129};
130
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100131/* permit to store configuration section */
132struct cfg_section {
133 struct list list;
134 char *section_name;
135 int (*section_parser)(const char *, int, char **, int);
136};
137
138/* Used to chain configuration sections definitions. This list
139 * stores struct cfg_section
140 */
141struct list sections = LIST_HEAD_INIT(sections);
142
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100145 const char *name;
146 unsigned int val;
147 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100148 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150};
151
152/* proxy->options */
153static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100154{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
156 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
157 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
158 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
159 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
160 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200162 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200163 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100164 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
166 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
167 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100169#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100171#else
172 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100173#endif
174
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100176};
177
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100178/* proxy->options2 */
179static const struct cfg_opt cfg_opts2[] =
180{
181#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
183 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
184 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100185#else
186 { "splice-request", 0, 0, 0, 0 },
187 { "splice-response", 0, 0, 0, 0 },
188 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100189#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100190 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
191 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
192 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
193 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
194 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
195 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
196 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
197 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
198 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400199 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100200 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200201 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200202 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100203 { NULL, 0, 0, 0 }
204};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau6daf3432008-01-22 16:44:08 +0100206static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
208int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100209int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100210char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200212/* List head of all known configuration keywords */
213static struct cfg_kw_list cfg_keywords = {
214 .list = LIST_HEAD_INIT(cfg_keywords.list)
215};
216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217/*
218 * converts <str> to a list of listeners which are dynamically allocated.
219 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
220 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
221 * - <port> is a numerical port from 1 to 65535 ;
222 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
223 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
225 * not NULL, it must be a valid pointer to either NULL or a freeable area that
226 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200228int 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 +0200229{
230 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 int port, end;
233
234 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200235
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100238 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
240 str = next;
241 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100242 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 *next++ = 0;
244 }
245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200247 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200248 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (!ss2)
250 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100252 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100258 if (!port || !end) {
259 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
260 goto fail;
261 }
262
Emeric Bruned760922010-10-22 17:59:25 +0200263 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
267
268 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200269 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200270 goto fail;
271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100273 else if (ss2->ss_family == AF_UNSPEC) {
274 socklen_t addr_len;
275
276 /* We want to attach to an already bound fd whose number
277 * is in the addr part of ss2 when cast to sockaddr_in.
278 * Note that by definition there is a single listener.
279 * We still have to determine the address family to
280 * register the correct protocol.
281 */
282 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
283 addr_len = sizeof(*ss2);
284 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
285 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
286 goto fail;
287 }
288
289 port = end = get_host_port(ss2);
290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100292 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200293 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100294
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200296 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100297 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200298 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
299 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
300 l->frontend = curproxy;
301 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau40aa0702013-03-10 23:51:38 +0100303 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200304 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200305 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100306 l->state = LI_INIT;
307
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100308 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 tcpv4_add_listener(l);
311 }
Emeric Bruned760922010-10-22 17:59:25 +0200312 else if (ss.ss_family == AF_INET6) {
313 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
314 tcpv6_add_listener(l);
315 }
316 else {
Emeric Bruned760922010-10-22 17:59:25 +0200317 uxst_add_listener(l);
318 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200320 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100321 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322 } /* end for(port) */
323 } /* end while(next) */
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326 fail:
327 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200328 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200329}
330
William Lallemand6e62fb62015-04-28 16:55:23 +0200331/*
332 * Report a fatal Alert when there is too much arguments
333 * The index is the current keyword in args
334 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
335 * Fill err_code with an ERR_ALERT and an ERR_FATAL
336 */
337int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
338{
339 char *kw = NULL;
340 int i;
341
342 if (!*args[index + maxarg + 1])
343 return 0;
344
345 memprintf(&kw, "%s", args[0]);
346 for (i = 1; i <= index; i++) {
347 memprintf(&kw, "%s %s", kw, args[i]);
348 }
349
350 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
351 free(kw);
352 *err_code |= ERR_ALERT | ERR_FATAL;
353 return 1;
354}
355
356/*
357 * same as alertif_too_many_args_idx with a 0 index
358 */
359int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
360{
361 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
362}
363
Willy Tarreau620408f2016-10-21 16:37:51 +0200364/* Report a warning if a rule is placed after a 'tcp-request session' rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
367int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
368{
369 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200377/* Report a warning if a rule is placed after a 'tcp-request content' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
380int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
381{
382 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
Willy Tarreau61d18892009-03-31 10:49:21 +0200390/* Report a warning if a rule is placed after a 'block' rule.
391 * Return 1 if the warning has been emitted, otherwise 0.
392 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200395 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200396 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
397 file, line, arg);
398 return 1;
399 }
400 return 0;
401}
402
Willy Tarreau5002f572014-04-23 01:32:02 +0200403/* Report a warning if a rule is placed after an 'http_request' rule.
404 * Return 1 if the warning has been emitted, otherwise 0.
405 */
406int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
407{
408 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
409 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
410 file, line, arg);
411 return 1;
412 }
413 return 0;
414}
415
Willy Tarreau61d18892009-03-31 10:49:21 +0200416/* Report a warning if a rule is placed after a reqrewrite rule.
417 * Return 1 if the warning has been emitted, otherwise 0.
418 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100419int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200420{
421 if (proxy->req_exp) {
422 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
423 file, line, arg);
424 return 1;
425 }
426 return 0;
427}
428
429/* Report a warning if a rule is placed after a reqadd rule.
430 * Return 1 if the warning has been emitted, otherwise 0.
431 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100434 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200435 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
436 file, line, arg);
437 return 1;
438 }
439 return 0;
440}
441
442/* Report a warning if a rule is placed after a redirect rule.
443 * Return 1 if the warning has been emitted, otherwise 0.
444 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100445int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200446{
447 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
448 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
449 file, line, arg);
450 return 1;
451 }
452 return 0;
453}
454
455/* Report a warning if a rule is placed after a 'use_backend' rule.
456 * Return 1 if the warning has been emitted, otherwise 0.
457 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100458int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200459{
460 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
461 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
462 file, line, arg);
463 return 1;
464 }
465 return 0;
466}
467
Willy Tarreauee445d92014-04-23 01:39:04 +0200468/* Report a warning if a rule is placed after a 'use-server' rule.
469 * Return 1 if the warning has been emitted, otherwise 0.
470 */
471int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
472{
473 if (!LIST_ISEMPTY(&proxy->server_rules)) {
474 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
475 file, line, arg);
476 return 1;
477 }
478 return 0;
479}
480
Willy Tarreaud39ad442016-11-25 15:16:12 +0100481/* report a warning if a redirect rule is dangerously placed */
482int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200483{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100484 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
Willy Tarreaud39ad442016-11-25 15:16:12 +0100488/* report a warning if a reqadd rule is dangerously placed */
489int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200490{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100491 return warnif_rule_after_redirect(proxy, file, line, arg) ||
492 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200493}
494
Willy Tarreaud39ad442016-11-25 15:16:12 +0100495/* report a warning if a reqxxx rule is dangerously placed */
496int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200497{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100498 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
499 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200500}
501
502/* report a warning if an http-request rule is dangerously placed */
503int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
504{
Willy Tarreau61d18892009-03-31 10:49:21 +0200505 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100506 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200507}
508
Willy Tarreaud39ad442016-11-25 15:16:12 +0100509/* report a warning if a block rule is dangerously placed */
510int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200511{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512 return warnif_rule_after_http_req(proxy, file, line, arg) ||
513 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200514}
515
Willy Tarreaud39ad442016-11-25 15:16:12 +0100516/* report a warning if a "tcp request content" rule is dangerously placed */
517int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519 return warnif_rule_after_block(proxy, file, line, arg) ||
520 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200521}
522
Willy Tarreaud39ad442016-11-25 15:16:12 +0100523/* report a warning if a "tcp request session" rule is dangerously placed */
524int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200525{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
527 warnif_misplaced_tcp_cont(proxy, file, line, arg);
528}
529
530/* report a warning if a "tcp request connection" rule is dangerously placed */
531int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
532{
533 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
534 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200535}
536
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100537/* Report it if a request ACL condition uses some keywords that are incompatible
538 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
539 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
540 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100543{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100544 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200545 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100547 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100548 return 0;
549
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100550 acl = acl_cond_conflicts(cond, where);
551 if (acl) {
552 if (acl->name && *acl->name)
553 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
554 file, line, acl->name, sample_ckp_names(where));
555 else
556 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 +0200557 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100558 return ERR_WARN;
559 }
560 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100561 return 0;
562
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563 if (acl->name && *acl->name)
564 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200565 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566 else
567 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200568 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100569 return ERR_WARN;
570}
571
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200573 * parse a line in a <global> section. Returns the error code, 0 if OK, or
574 * any combination of :
575 * - ERR_ABORT: must abort ASAP
576 * - ERR_FATAL: we can continue parsing but not start the service
577 * - ERR_WARN: a warning has been emitted
578 * - ERR_ALERT: an alert has been emitted
579 * Only the two first ones can stop processing, the two others are just
580 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200582int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583{
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200585 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586
587 if (!strcmp(args[0], "global")) { /* new section */
588 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200589 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200592 else if (!strcmp(args[0], "ca-base")) {
593#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200594 if(alertif_too_many_args(1, file, linenum, args, &err_code))
595 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200596 if (global.ca_base != NULL) {
597 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT;
599 goto out;
600 }
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.ca_base = strdup(args[1]);
607#else
608 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611#endif
612 }
613 else if (!strcmp(args[0], "crt-base")) {
614#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200615 if (alertif_too_many_args(1, file, linenum, args, &err_code))
616 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200617 if (global.crt_base != NULL) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.crt_base = strdup(args[1]);
628#else
629 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
630 err_code |= ERR_ALERT | ERR_FATAL;
631 goto out;
632#endif
633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200635 if (alertif_too_many_args(0, file, linenum, args, &err_code))
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 global.mode |= MODE_DAEMON;
638 }
639 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200640 if (alertif_too_many_args(0, file, linenum, args, &err_code))
641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 global.mode |= MODE_DEBUG;
643 }
644 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200645 if (alertif_too_many_args(0, file, linenum, args, &err_code))
646 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100647 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200649 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200650 if (alertif_too_many_args(0, file, linenum, args, &err_code))
651 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100652 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200655 if (alertif_too_many_args(0, file, linenum, args, &err_code))
656 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100657 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100659 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200660 if (alertif_too_many_args(0, file, linenum, args, &err_code))
661 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 global.tune.options &= ~GTUNE_USE_SPLICE;
663 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200664 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200665 if (alertif_too_many_args(0, file, linenum, args, &err_code))
666 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 global.tune.options &= ~GTUNE_USE_GAI;
668 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000669 else if (!strcmp(args[0], "noreuseport")) {
670 if (alertif_too_many_args(0, file, linenum, args, &err_code))
671 goto out;
672 global.tune.options &= ~GTUNE_USE_REUSEPORT;
673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200675 if (alertif_too_many_args(0, file, linenum, args, &err_code))
676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 global.mode |= MODE_QUIET;
678 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200680 if (alertif_too_many_args(1, file, linenum, args, &err_code))
681 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 if (global.tune.maxpollevents != 0) {
683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200684 err_code |= ERR_ALERT;
685 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200686 }
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200691 }
692 global.tune.maxpollevents = atol(args[1]);
693 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200695 if (alertif_too_many_args(1, file, linenum, args, &err_code))
696 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 if (global.tune.maxaccept != 0) {
698 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT;
700 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100701 }
702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100706 }
707 global.tune.maxaccept = atol(args[1]);
708 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200709 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200710 if (alertif_too_many_args(1, file, linenum, args, &err_code))
711 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.chksize = atol(args[1]);
718 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100719 else if (!strcmp(args[0], "tune.recv_enough")) {
720 if (alertif_too_many_args(1, file, linenum, args, &err_code))
721 goto out;
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
726 }
727 global.tune.recv_enough = atol(args[1]);
728 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200729#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200730 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200731 if (alertif_too_many_args(0, file, linenum, args, &err_code))
732 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200733 global.tune.sslprivatecache = 1;
734 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100735 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
737 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.sslcachesize = atol(args[1]);
744 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100745 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
746 unsigned int ssllifetime;
747 const char *res;
748
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
758 if (res) {
759 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
760 file, linenum, *res, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 global.tune.ssllifetime = ssllifetime;
766 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100767 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200768 if (alertif_too_many_args(1, file, linenum, args, &err_code))
769 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100770 if (*(args[1]) == 0) {
771 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 global.tune.ssl_max_record = atol(args[1]);
776 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200777#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200778 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200779 if (alertif_too_many_args(1, file, linenum, args, &err_code))
780 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.ssl_default_dh_param = atol(args[1]);
787 if (global.tune.ssl_default_dh_param < 1024) {
788 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
791 }
792 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200793#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200794 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
795 if (alertif_too_many_args(1, file, linenum, args, &err_code))
796 goto out;
797 if (*(args[1]) == 0) {
798 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 global.tune.ssl_ctx_cache = atoi(args[1]);
803 if (global.tune.ssl_ctx_cache < 0) {
804 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
805 file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200810#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100811 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200812 if (alertif_too_many_args(1, file, linenum, args, &err_code))
813 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.buf_limit = atol(args[1]);
820 if (global.tune.buf_limit) {
821 if (global.tune.buf_limit < 3)
822 global.tune.buf_limit = 3;
823 if (global.tune.buf_limit <= global.tune.reserved_bufs)
824 global.tune.buf_limit = global.tune.reserved_bufs + 1;
825 }
826 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100827 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200828 if (alertif_too_many_args(1, file, linenum, args, &err_code))
829 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835 global.tune.reserved_bufs = atol(args[1]);
836 if (global.tune.reserved_bufs < 2)
837 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100838 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
839 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100840 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200841 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
843 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200850 if (global.tune.bufsize <= 0) {
851 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100855 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100856 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200857 }
858 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200859 if (alertif_too_many_args(1, file, linenum, args, &err_code))
860 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200861 if (*(args[1]) == 0) {
862 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200867 if (global.tune.maxrewrite < 0) {
868 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200872 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100873 else if (!strcmp(args[0], "tune.idletimer")) {
874 unsigned int idle;
875 const char *res;
876
William Lallemand1a748ae2015-05-19 16:37:23 +0200877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
878 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884
885 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
886 if (res) {
887 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
888 file, linenum, *res, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892
893 if (idle > 65535) {
894 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898 global.tune.idle_timer = idle;
899 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100900 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100903 if (global.tune.client_rcvbuf != 0) {
904 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT;
906 goto out;
907 }
908 if (*(args[1]) == 0) {
909 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 global.tune.client_rcvbuf = atol(args[1]);
914 }
915 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200916 if (alertif_too_many_args(1, file, linenum, args, &err_code))
917 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100918 if (global.tune.server_rcvbuf != 0) {
919 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT;
921 goto out;
922 }
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 global.tune.server_rcvbuf = atol(args[1]);
929 }
930 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
932 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100933 if (global.tune.client_sndbuf != 0) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT;
936 goto out;
937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.tune.client_sndbuf = atol(args[1]);
944 }
945 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200946 if (alertif_too_many_args(1, file, linenum, args, &err_code))
947 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100948 if (global.tune.server_sndbuf != 0) {
949 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
950 err_code |= ERR_ALERT;
951 goto out;
952 }
953 if (*(args[1]) == 0) {
954 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
957 }
958 global.tune.server_sndbuf = atol(args[1]);
959 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200960 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200961 if (alertif_too_many_args(1, file, linenum, args, &err_code))
962 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
967 }
968 global.tune.pipesize = atol(args[1]);
969 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100970 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200971 if (alertif_too_many_args(1, file, linenum, args, &err_code))
972 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 global.tune.cookie_len = atol(args[1]) + 1;
979 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200980 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200981 if (alertif_too_many_args(1, file, linenum, args, &err_code))
982 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 global.tune.max_http_hdr = atol(args[1]);
989 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100990 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
991#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200992 if (alertif_too_many_args(1, file, linenum, args, &err_code))
993 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100994 if (*args[1]) {
995 global.tune.zlibmemlevel = atoi(args[1]);
996 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
997 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
998 file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 } else {
1003 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1004 file, linenum, args[0]);
1005 err_code |= ERR_ALERT | ERR_FATAL;
1006 goto out;
1007 }
1008#else
1009 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012#endif
1013 }
1014 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1015#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001016 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1017 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001018 if (*args[1]) {
1019 global.tune.zlibwindowsize = atoi(args[1]);
1020 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1021 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 } else {
1027 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
William Lallemandf3747832012-11-09 12:33:10 +01001038 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001039 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1040 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001041 if (*args[1]) {
1042 global.tune.comp_maxlevel = atoi(args[1]);
1043 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1044 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1045 file, linenum, args[0]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 } else {
1050 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1051 file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
1055 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001056 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1057 if (*args[1]) {
1058 global.tune.pattern_cache = atoi(args[1]);
1059 if (global.tune.pattern_cache < 0) {
1060 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1061 file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 } else {
1066 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1067 file, linenum, args[0]);
1068 err_code |= ERR_ALERT | ERR_FATAL;
1069 goto out;
1070 }
1071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001073 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001076 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT;
1078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 }
1080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001085 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1086 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]);
1087 err_code |= ERR_WARN;
1088 goto out;
1089 }
1090
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
1092 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001093 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001096 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001097 err_code |= ERR_ALERT;
1098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 }
1100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001105 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1106 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]);
1107 err_code |= ERR_WARN;
1108 goto out;
1109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
Simon Horman98637e52014-06-20 12:30:16 +09001111 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001112 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1113 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001114 global.external_check = 1;
1115 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001116 /* user/group name handling */
1117 else if (!strcmp(args[0], "user")) {
1118 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001119 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1120 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001121 if (global.uid != 0) {
1122 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001125 }
1126 errno = 0;
1127 ha_user = getpwnam(args[1]);
1128 if (ha_user != NULL) {
1129 global.uid = (int)ha_user->pw_uid;
1130 }
1131 else {
1132 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 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001134 }
1135 }
1136 else if (!strcmp(args[0], "group")) {
1137 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1139 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001140 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001141 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT;
1143 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001144 }
1145 errno = 0;
1146 ha_group = getgrnam(args[1]);
1147 if (ha_group != NULL) {
1148 global.gid = (int)ha_group->gr_gid;
1149 }
1150 else {
1151 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 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001153 }
1154 }
1155 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 if (*(args[1]) == 0) {
1160 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001165 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1166 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1167 file, linenum, args[0], LONGBITS, global.nbproc);
1168 err_code |= ERR_ALERT | ERR_FATAL;
1169 goto out;
1170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 }
1172 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001173 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 if (global.maxconn != 0) {
1176 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001177 err_code |= ERR_ALERT;
1178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 }
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 }
1185 global.maxconn = atol(args[1]);
1186#ifdef SYSTEM_MAXCONN
1187 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1188 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);
1189 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001190 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 }
1192#endif /* SYSTEM_MAXCONN */
1193 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001194 else if (!strcmp(args[0], "maxsslconn")) {
1195#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001198 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.maxsslconn = atol(args[1]);
1204#else
Emeric Brun0914df82012-10-02 18:45:42 +02001205 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001208#endif
1209 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001210 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1211#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001212 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1213 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001214 if (*(args[1]) == 0) {
1215 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219 free(global.listen_default_ciphers);
1220 global.listen_default_ciphers = strdup(args[1]);
1221#else
1222 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 goto out;
1225#endif
1226 }
1227 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1228#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001229 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1230 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 free(global.connect_default_ciphers);
1237 global.connect_default_ciphers = strdup(args[1]);
1238#else
1239 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242#endif
1243 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001244#ifdef USE_OPENSSL
1245#ifndef OPENSSL_NO_DH
1246 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1253 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257 }
1258#endif
1259#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001260 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001261 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1262 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001263 if (*(args[1]) == 0) {
1264 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268 if (strcmp(args[1],"none") == 0)
1269 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1270 else if (strcmp(args[1],"required") == 0)
1271 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1272 else {
1273 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001278 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001279 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1280 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001281 if (global.cps_lim != 0) {
1282 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1283 err_code |= ERR_ALERT;
1284 goto out;
1285 }
1286 if (*(args[1]) == 0) {
1287 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291 global.cps_lim = atol(args[1]);
1292 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001293 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001294 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1295 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001296 if (global.sps_lim != 0) {
1297 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1298 err_code |= ERR_ALERT;
1299 goto out;
1300 }
1301 if (*(args[1]) == 0) {
1302 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306 global.sps_lim = atol(args[1]);
1307 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001308 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001309 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1310 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001311 if (global.ssl_lim != 0) {
1312 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1313 err_code |= ERR_ALERT;
1314 goto out;
1315 }
1316 if (*(args[1]) == 0) {
1317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
1321 global.ssl_lim = atol(args[1]);
1322 }
William Lallemandd85f9172012-11-09 17:05:39 +01001323 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001324 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1325 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001326 if (*(args[1]) == 0) {
1327 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 global.comp_rate_lim = atoi(args[1]) * 1024;
1332 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001333 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001334 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1335 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001336 if (global.maxpipes != 0) {
1337 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001338 err_code |= ERR_ALERT;
1339 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001340 }
1341 if (*(args[1]) == 0) {
1342 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001345 }
1346 global.maxpipes = atol(args[1]);
1347 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001348 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001349 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1350 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001351 if (*(args[1]) == 0) {
1352 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
William Lallemande3a7d992012-11-20 11:25:20 +01001356 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001357 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001358 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001361 if (*(args[1]) == 0) {
1362 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
1365 }
1366 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001367 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001368 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
1371 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001372 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001373
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001375 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 if (global.rlimit_nofile != 0) {
1378 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001379 err_code |= ERR_ALERT;
1380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 }
1382 if (*(args[1]) == 0) {
1383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001384 err_code |= ERR_ALERT | ERR_FATAL;
1385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 }
1387 global.rlimit_nofile = atol(args[1]);
1388 }
1389 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001390 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 if (global.chroot != NULL) {
1393 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001394 err_code |= ERR_ALERT;
1395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 }
1397 if (*(args[1]) == 0) {
1398 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001399 err_code |= ERR_ALERT | ERR_FATAL;
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
1402 global.chroot = strdup(args[1]);
1403 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001404 else if (!strcmp(args[0], "description")) {
1405 int i, len=0;
1406 char *d;
1407
1408 if (!*args[1]) {
1409 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1410 file, linenum, args[0]);
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
Willy Tarreau348acfe2014-04-14 15:00:39 +02001415 for (i = 1; *args[i]; i++)
1416 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001417
1418 if (global.desc)
1419 free(global.desc);
1420
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001421 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001422
Willy Tarreau348acfe2014-04-14 15:00:39 +02001423 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1424 for (i = 2; *args[i]; i++)
1425 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001426 }
1427 else if (!strcmp(args[0], "node")) {
1428 int i;
1429 char c;
1430
William Lallemand1a748ae2015-05-19 16:37:23 +02001431 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1432 goto out;
1433
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001434 for (i=0; args[1][i]; i++) {
1435 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001436 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1437 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001438 break;
1439 }
1440
1441 if (!i || args[1][i]) {
1442 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1443 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1444 file, linenum, args[0]);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448
1449 if (global.node)
1450 free(global.node);
1451
1452 global.node = strdup(args[1]);
1453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001455 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 if (global.pidfile != NULL) {
1458 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001459 err_code |= ERR_ALERT;
1460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 }
1467 global.pidfile = strdup(args[1]);
1468 }
Emeric Bruned760922010-10-22 17:59:25 +02001469 else if (!strcmp(args[0], "unix-bind")) {
1470 int cur_arg = 1;
1471 while (*(args[cur_arg])) {
1472 if (!strcmp(args[cur_arg], "prefix")) {
1473 if (global.unix_bind.prefix != NULL) {
1474 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1475 err_code |= ERR_ALERT;
1476 cur_arg += 2;
1477 continue;
1478 }
1479
1480 if (*(args[cur_arg+1]) == 0) {
1481 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1486 cur_arg += 2;
1487 continue;
1488 }
1489
1490 if (!strcmp(args[cur_arg], "mode")) {
1491
1492 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1493 cur_arg += 2;
1494 continue;
1495 }
1496
1497 if (!strcmp(args[cur_arg], "uid")) {
1498
1499 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (!strcmp(args[cur_arg], "gid")) {
1505
1506 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1507 cur_arg += 2;
1508 continue;
1509 }
1510
1511 if (!strcmp(args[cur_arg], "user")) {
1512 struct passwd *user;
1513
1514 user = getpwnam(args[cur_arg + 1]);
1515 if (!user) {
1516 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1517 file, linenum, args[0], args[cur_arg + 1 ]);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521
1522 global.unix_bind.ux.uid = user->pw_uid;
1523 cur_arg += 2;
1524 continue;
1525 }
1526
1527 if (!strcmp(args[cur_arg], "group")) {
1528 struct group *group;
1529
1530 group = getgrnam(args[cur_arg + 1]);
1531 if (!group) {
1532 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1533 file, linenum, args[0], args[cur_arg + 1 ]);
1534 err_code |= ERR_ALERT | ERR_FATAL;
1535 goto out;
1536 }
1537
1538 global.unix_bind.ux.gid = group->gr_gid;
1539 cur_arg += 2;
1540 continue;
1541 }
1542
Willy Tarreaub48f9582011-09-05 01:17:06 +02001543 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001544 file, linenum, args[0]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548 }
William Lallemand0f99e342011-10-12 17:50:54 +02001549 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1550 /* delete previous herited or defined syslog servers */
1551 struct logsrv *back;
1552 struct logsrv *tmp;
1553
1554 if (*(args[1]) != 0) {
1555 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558 }
1559
1560 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1561 LIST_DEL(&tmp->list);
1562 free(tmp);
1563 }
1564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001566 struct sockaddr_storage *sk;
1567 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001568 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001569 int arg = 0;
1570 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001571
William Lallemand1a748ae2015-05-19 16:37:23 +02001572 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1573 goto out;
1574
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 if (*(args[1]) == 0 || *(args[2]) == 0) {
1576 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
William Lallemand0f99e342011-10-12 17:50:54 +02001580
Vincent Bernat02779b62016-04-03 13:48:43 +02001581 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001582
Willy Tarreau18324f52014-06-27 18:10:07 +02001583 /* just after the address, a length may be specified */
1584 if (strcmp(args[arg+2], "len") == 0) {
1585 len = atoi(args[arg+3]);
1586 if (len < 80 || len > 65535) {
1587 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1588 file, linenum, args[arg+3]);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592 logsrv->maxlen = len;
1593
1594 /* skip these two args */
1595 arg += 2;
1596 }
1597 else
1598 logsrv->maxlen = MAX_SYSLOG_LEN;
1599
1600 if (logsrv->maxlen > global.max_syslog_len) {
1601 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001602 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1603 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1604 logline = my_realloc2(logline, global.max_syslog_len + 1);
1605 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001606 }
1607
Dragan Dosen1322d092015-09-22 16:05:32 +02001608 /* after the length, a format may be specified */
1609 if (strcmp(args[arg+2], "format") == 0) {
1610 logsrv->format = get_log_format(args[arg+3]);
1611 if (logsrv->format < 0) {
1612 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1613 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001614 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001615 goto out;
1616 }
1617
1618 /* skip these two args */
1619 arg += 2;
1620 }
1621
David Carlier97880bb2016-04-08 10:35:26 +01001622 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1623 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001624 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001625 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001626
Willy Tarreau18324f52014-06-27 18:10:07 +02001627 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001628 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001629 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001631 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 }
1633
William Lallemand0f99e342011-10-12 17:50:54 +02001634 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001635 if (*(args[arg+3])) {
1636 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001637 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001638 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001640 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 }
1642 }
1643
William Lallemand0f99e342011-10-12 17:50:54 +02001644 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001645 if (*(args[arg+4])) {
1646 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001647 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001648 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001649 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001650 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001651 }
1652 }
1653
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001654 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001655 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001656 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001657 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001658 free(logsrv);
1659 goto out;
1660 }
1661 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001662
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001663 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001664 if (port1 != port2) {
1665 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1666 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001667 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001668 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001669 goto out;
1670 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001671
William Lallemand0f99e342011-10-12 17:50:54 +02001672 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001673 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001674 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676
William Lallemand0f99e342011-10-12 17:50:54 +02001677 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001678 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001679 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1680 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001681
1682 if (global.log_send_hostname != NULL) {
1683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1684 err_code |= ERR_ALERT;
1685 goto out;
1686 }
1687
1688 if (*(args[1]))
1689 name = args[1];
1690 else
1691 name = hostname;
1692
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001693 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001694 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001695 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001696 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1697 if (global.server_state_base != NULL) {
1698 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1699 err_code |= ERR_ALERT;
1700 goto out;
1701 }
1702
1703 if (!*(args[1])) {
1704 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1705 err_code |= ERR_FATAL;
1706 goto out;
1707 }
1708
1709 global.server_state_base = strdup(args[1]);
1710 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001711 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1712 if (global.server_state_file != NULL) {
1713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1714 err_code |= ERR_ALERT;
1715 goto out;
1716 }
1717
1718 if (!*(args[1])) {
1719 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1720 err_code |= ERR_FATAL;
1721 goto out;
1722 }
1723
1724 global.server_state_file = strdup(args[1]);
1725 }
Kevinm48936af2010-12-22 16:08:21 +00001726 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001727 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1728 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001729 if (*(args[1]) == 0) {
1730 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
1733 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001734 chunk_destroy(&global.log_tag);
1735 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001736 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001737 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001738 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1739 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001740 if (global.spread_checks != 0) {
1741 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001742 err_code |= ERR_ALERT;
1743 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001744 }
1745 if (*(args[1]) == 0) {
1746 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001749 }
1750 global.spread_checks = atol(args[1]);
1751 if (global.spread_checks < 0 || global.spread_checks > 50) {
1752 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001756 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1757 const char *err;
1758 unsigned int val;
1759
William Lallemand1a748ae2015-05-19 16:37:23 +02001760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1761 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001762 if (*(args[1]) == 0) {
1763 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
1768 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1769 if (err) {
1770 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1771 err_code |= ERR_ALERT | ERR_FATAL;
1772 }
1773 global.max_spread_checks = val;
1774 if (global.max_spread_checks < 0) {
1775 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1776 err_code |= ERR_ALERT | ERR_FATAL;
1777 }
1778 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001779 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1780#ifdef USE_CPU_AFFINITY
1781 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001782 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001783 unsigned long cpus = 0;
1784
1785 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001786 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001787 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001788 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001789 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001790 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001791 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001792 proc = atol(args[1]);
1793 if (proc >= 1 && proc <= LONGBITS)
1794 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001795 }
1796
1797 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001798 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1799 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802 }
1803
1804 cur_arg = 2;
1805 while (*args[cur_arg]) {
1806 unsigned int low, high;
1807
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001808 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001809 char *dash = strchr(args[cur_arg], '-');
1810
1811 low = high = str2uic(args[cur_arg]);
1812 if (dash)
1813 high = str2uic(dash + 1);
1814
1815 if (high < low) {
1816 unsigned int swap = low;
1817 low = high;
1818 high = swap;
1819 }
1820
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001821 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001822 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001823 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 while (low <= high)
1829 cpus |= 1UL << low++;
1830 }
1831 else {
1832 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1833 file, linenum, args[0], args[cur_arg]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837 cur_arg++;
1838 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001839 for (i = 0; i < LONGBITS; i++)
1840 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001841 global.cpu_map[i] = cpus;
1842#else
1843 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846#endif
1847 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001848 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1849 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1850 goto out;
1851
1852 if (*(args[2]) == 0) {
1853 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1859 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1860 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
1863 }
1864 }
1865 else if (!strcmp(args[0], "unsetenv")) {
1866 int arg;
1867
1868 if (*(args[1]) == 0) {
1869 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872 }
1873
1874 for (arg = 1; *args[arg]; arg++) {
1875 if (unsetenv(args[arg]) != 0) {
1876 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
1879 }
1880 }
1881 }
1882 else if (!strcmp(args[0], "resetenv")) {
1883 extern char **environ;
1884 char **env = environ;
1885
1886 /* args contain variable names to keep, one per argument */
1887 while (*env) {
1888 int arg;
1889
1890 /* look for current variable in among all those we want to keep */
1891 for (arg = 1; *args[arg]; arg++) {
1892 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1893 (*env)[strlen(args[arg])] == '=')
1894 break;
1895 }
1896
1897 /* delete this variable */
1898 if (!*args[arg]) {
1899 char *delim = strchr(*env, '=');
1900
1901 if (!delim || delim - *env >= trash.size) {
1902 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1903 err_code |= ERR_ALERT | ERR_FATAL;
1904 goto out;
1905 }
1906
1907 memcpy(trash.str, *env, delim - *env);
1908 trash.str[delim - *env] = 0;
1909
1910 if (unsetenv(trash.str) != 0) {
1911 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
1914 }
1915 }
1916 else
1917 env++;
1918 }
1919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001921 struct cfg_kw_list *kwl;
1922 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001923 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001924
1925 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1926 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1927 if (kwl->kw[index].section != CFG_GLOBAL)
1928 continue;
1929 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001930 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001931 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001932 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001934 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001935 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001936 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001937 err_code |= ERR_WARN;
1938 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001939 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001940 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001941 }
1942 }
1943 }
1944
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001948
Willy Tarreau058e9072009-07-20 09:30:05 +02001949 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001950 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001951 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952}
1953
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001954void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001956 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 defproxy.mode = PR_MODE_TCP;
1958 defproxy.state = PR_STNEW;
1959 defproxy.maxconn = cfg_maxpconn;
1960 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001961 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001962 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001963
Simon Horman66183002013-02-23 10:16:43 +09001964 defproxy.defsrv.check.inter = DEF_CHKINTR;
1965 defproxy.defsrv.check.fastinter = 0;
1966 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001967 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1968 defproxy.defsrv.agent.fastinter = 0;
1969 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001970 defproxy.defsrv.check.rise = DEF_RISETIME;
1971 defproxy.defsrv.check.fall = DEF_FALLTIME;
1972 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1973 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001974 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001975 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001976 defproxy.defsrv.maxqueue = 0;
1977 defproxy.defsrv.minconn = 0;
1978 defproxy.defsrv.maxconn = 0;
1979 defproxy.defsrv.slowstart = 0;
1980 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1981 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1982 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001983
1984 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001985 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986}
1987
Willy Tarreauade5ec42010-01-28 19:33:49 +01001988
Willy Tarreau63af98d2014-05-18 08:11:41 +02001989/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1990 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1991 * ERR_FATAL in case of error.
1992 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001993static int create_cond_regex_rule(const char *file, int line,
1994 struct proxy *px, int dir, int action, int flags,
1995 const char *cmd, const char *reg, const char *repl,
1996 const char **cond_start)
1997{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001998 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001999 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002000 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002001 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002002 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002003 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002004 int cs;
2005 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002006
2007 if (px == &defproxy) {
2008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002009 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002010 goto err;
2011 }
2012
2013 if (*reg == 0) {
2014 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002015 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002016 goto err;
2017 }
2018
Christopher Faulet898566e2016-10-26 11:06:28 +02002019 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002020 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002021
Willy Tarreau5321c422010-01-28 20:35:13 +01002022 if (cond_start &&
2023 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002024 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2025 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2026 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002028 goto err;
2029 }
2030 }
2031 else if (cond_start && **cond_start) {
2032 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2033 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002034 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002035 goto err;
2036 }
2037
Willy Tarreau63af98d2014-05-18 08:11:41 +02002038 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002039 (dir == SMP_OPT_DIR_REQ) ?
2040 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2041 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2042 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002043
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002044 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002045 if (!preg) {
2046 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002047 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002048 goto err;
2049 }
2050
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002051 cs = !(flags & REG_ICASE);
2052 cap = !(flags & REG_NOSUB);
2053 error = NULL;
2054 if (!regex_comp(reg, preg, cs, cap, &error)) {
2055 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2056 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002057 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002058 goto err;
2059 }
2060
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002061 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002062 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002063 if (repl && err) {
2064 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2065 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002066 ret_code |= ERR_ALERT | ERR_FATAL;
2067 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002068 }
2069
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002070 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002071 ret_code |= ERR_WARN;
2072
2073 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002074
Willy Tarreau63af98d2014-05-18 08:11:41 +02002075 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002076 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002077 err:
2078 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002079 free(errmsg);
2080 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002081}
2082
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083/*
William Lallemand51097192015-04-14 16:35:22 +02002084 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002085 * Returns the error code, 0 if OK, or any combination of :
2086 * - ERR_ABORT: must abort ASAP
2087 * - ERR_FATAL: we can continue parsing but not start the service
2088 * - ERR_WARN: a warning has been emitted
2089 * - ERR_ALERT: an alert has been emitted
2090 * Only the two first ones can stop processing, the two others are just
2091 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002093int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2094{
2095 static struct peers *curpeers = NULL;
2096 struct peer *newpeer = NULL;
2097 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002098 struct bind_conf *bind_conf;
2099 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002101 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002102
2103 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002104 if (!*args[1]) {
2105 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002106 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002107 goto out;
2108 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002109
William Lallemand6e62fb62015-04-28 16:55:23 +02002110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2111 goto out;
2112
Emeric Brun32da3c42010-09-23 18:39:19 +02002113 err = invalid_char(args[1]);
2114 if (err) {
2115 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2116 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002117 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002118 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002119 }
2120
2121 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2122 /*
2123 * If there are two proxies with the same name only following
2124 * combinations are allowed:
2125 */
2126 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002127 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 +02002128 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002130 }
2131 }
2132
Vincent Bernat02779b62016-04-03 13:48:43 +02002133 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2135 err_code |= ERR_ALERT | ERR_ABORT;
2136 goto out;
2137 }
2138
2139 curpeers->next = peers;
2140 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002141 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002142 curpeers->conf.line = linenum;
2143 curpeers->last_change = now.tv_sec;
2144 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002145 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002146 }
2147 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002148 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002149 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002150 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002151
2152 if (!*args[2]) {
2153 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2154 file, linenum, args[0]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158
2159 err = invalid_char(args[1]);
2160 if (err) {
2161 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2162 file, linenum, *err, args[1]);
2163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
2165 }
2166
Vincent Bernat02779b62016-04-03 13:48:43 +02002167 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2169 err_code |= ERR_ALERT | ERR_ABORT;
2170 goto out;
2171 }
2172
2173 /* the peers are linked backwards first */
2174 curpeers->count++;
2175 newpeer->next = curpeers->remote;
2176 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002177 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002178 newpeer->conf.line = linenum;
2179
2180 newpeer->last_change = now.tv_sec;
2181 newpeer->id = strdup(args[1]);
2182
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002183 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002184 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002185 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002188 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002189
2190 proto = protocol_by_family(sk->ss_family);
2191 if (!proto || !proto->connect) {
2192 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2193 file, linenum, args[0], args[1]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002197
2198 if (port1 != port2) {
2199 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2200 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
2203 }
2204
Willy Tarreau2aa38802013-02-20 19:20:59 +01002205 if (!port1) {
2206 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2207 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
2209 goto out;
2210 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002211
Emeric Brun32da3c42010-09-23 18:39:19 +02002212 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002213 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002214 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002215 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002216
Emeric Brun32da3c42010-09-23 18:39:19 +02002217 if (strcmp(newpeer->id, localpeer) == 0) {
2218 /* Current is local peer, it define a frontend */
2219 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002220 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002221
2222 if (!curpeers->peers_fe) {
2223 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2225 err_code |= ERR_ALERT | ERR_ABORT;
2226 goto out;
2227 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002228
Willy Tarreau237250c2011-07-29 01:49:03 +02002229 init_new_proxy(curpeers->peers_fe);
2230 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002231 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002232 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2233 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002234 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002235
2236 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2237
Willy Tarreau902636f2013-03-10 19:44:48 +01002238 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2239 if (errmsg && *errmsg) {
2240 indent_msg(&errmsg, 2);
2241 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002242 }
2243 else
2244 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2245 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002246 err_code |= ERR_FATAL;
2247 goto out;
2248 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002249
2250 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002251 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002252 l->maxconn = curpeers->peers_fe->maxconn;
2253 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002254 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002255 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002256 l->analysers |= curpeers->peers_fe->fe_req_ana;
2257 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002258 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2259 global.maxsock += l->maxconn;
2260 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002261 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002262 else {
2263 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2264 file, linenum, args[0], args[1],
2265 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2266 err_code |= ERR_FATAL;
2267 goto out;
2268 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002269 }
2270 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002271 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2272 curpeers->state = PR_STSTOPPED;
2273 }
2274 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2275 curpeers->state = PR_STNEW;
2276 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002277 else if (*args[0] != 0) {
2278 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282
2283out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002284 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002285 return err_code;
2286}
2287
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288/*
2289 * Parse a <resolvers> section.
2290 * Returns the error code, 0 if OK, or any combination of :
2291 * - ERR_ABORT: must abort ASAP
2292 * - ERR_FATAL: we can continue parsing but not start the service
2293 * - ERR_WARN: a warning has been emitted
2294 * - ERR_ALERT: an alert has been emitted
2295 * Only the two first ones can stop processing, the two others are just
2296 * indicators.
2297 */
2298int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2299{
2300 static struct dns_resolvers *curr_resolvers = NULL;
2301 struct dns_nameserver *newnameserver = NULL;
2302 const char *err;
2303 int err_code = 0;
2304 char *errmsg = NULL;
2305
2306 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2307 if (!*args[1]) {
2308 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2309 err_code |= ERR_ALERT | ERR_ABORT;
2310 goto out;
2311 }
2312
2313 err = invalid_char(args[1]);
2314 if (err) {
2315 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2316 file, linenum, *err, args[0], args[1]);
2317 err_code |= ERR_ALERT | ERR_ABORT;
2318 goto out;
2319 }
2320
2321 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2322 /* Error if two resolvers owns the same name */
2323 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2324 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2325 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2326 err_code |= ERR_ALERT | ERR_ABORT;
2327 }
2328 }
2329
Vincent Bernat02779b62016-04-03 13:48:43 +02002330 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002331 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2332 err_code |= ERR_ALERT | ERR_ABORT;
2333 goto out;
2334 }
2335
2336 /* default values */
2337 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2338 curr_resolvers->conf.file = strdup(file);
2339 curr_resolvers->conf.line = linenum;
2340 curr_resolvers->id = strdup(args[1]);
2341 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002342 /* default hold period for nx, other, refuse and timeout is 30s */
2343 curr_resolvers->hold.nx = 30000;
2344 curr_resolvers->hold.other = 30000;
2345 curr_resolvers->hold.refused = 30000;
2346 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002347 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002348 curr_resolvers->hold.valid = 10000;
2349 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002350 curr_resolvers->resolve_retries = 3;
2351 LIST_INIT(&curr_resolvers->nameserver_list);
2352 LIST_INIT(&curr_resolvers->curr_resolution);
2353 }
2354 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2355 struct sockaddr_storage *sk;
2356 int port1, port2;
2357 struct protocol *proto;
2358
2359 if (!*args[2]) {
2360 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2361 file, linenum, args[0]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
2366 err = invalid_char(args[1]);
2367 if (err) {
2368 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2369 file, linenum, *err, args[1]);
2370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
2372 }
2373
Baptiste Assmanna315c552015-11-02 22:55:49 +01002374 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2375 /* Error if two resolvers owns the same name */
2376 if (strcmp(newnameserver->id, args[1]) == 0) {
2377 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2378 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 }
2381 }
2382
Vincent Bernat02779b62016-04-03 13:48:43 +02002383 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2385 err_code |= ERR_ALERT | ERR_ABORT;
2386 goto out;
2387 }
2388
2389 /* the nameservers are linked backward first */
2390 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2391 curr_resolvers->count_nameservers++;
2392 newnameserver->resolvers = curr_resolvers;
2393 newnameserver->conf.file = strdup(file);
2394 newnameserver->conf.line = linenum;
2395 newnameserver->id = strdup(args[1]);
2396
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002397 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002398 if (!sk) {
2399 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
2402 }
2403
2404 proto = protocol_by_family(sk->ss_family);
2405 if (!proto || !proto->connect) {
2406 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2407 file, linenum, args[0], args[1]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 if (port1 != port2) {
2413 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2414 file, linenum, args[0], args[1], args[2]);
2415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
2417 }
2418
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002419 if (!port1 && !port2) {
2420 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2421 file, linenum, args[0], args[1]);
2422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
2424 }
2425
Baptiste Assmann325137d2015-04-13 23:40:55 +02002426 newnameserver->addr = *sk;
2427 }
2428 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2429 const char *res;
2430 unsigned int time;
2431
2432 if (!*args[2]) {
2433 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2434 file, linenum, args[0]);
2435 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2440 if (res) {
2441 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2442 file, linenum, *res, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002446 if (strcmp(args[1], "nx") == 0)
2447 curr_resolvers->hold.nx = time;
2448 else if (strcmp(args[1], "other") == 0)
2449 curr_resolvers->hold.other = time;
2450 else if (strcmp(args[1], "refused") == 0)
2451 curr_resolvers->hold.refused = time;
2452 else if (strcmp(args[1], "timeout") == 0)
2453 curr_resolvers->hold.timeout = time;
2454 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002455 curr_resolvers->hold.valid = time;
2456 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002457 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2458 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462
2463 }
2464 else if (strcmp(args[0], "resolve_retries") == 0) {
2465 if (!*args[1]) {
2466 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2467 file, linenum, args[0]);
2468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
2470 }
2471 curr_resolvers->resolve_retries = atoi(args[1]);
2472 }
2473 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002474 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002475 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2476 file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002480 else if (strcmp(args[1], "retry") == 0) {
2481 const char *res;
2482 unsigned int timeout_retry;
2483
2484 if (!*args[2]) {
2485 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2486 file, linenum, args[0], args[1]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2491 if (res) {
2492 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2493 file, linenum, *res, args[0], args[1]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497 curr_resolvers->timeout.retry = timeout_retry;
2498 }
2499 else {
2500 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2501 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002505 } /* neither "nameserver" nor "resolvers" */
2506 else if (*args[0] != 0) {
2507 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
2512 out:
2513 free(errmsg);
2514 return err_code;
2515}
Simon Horman0d16a402015-01-30 11:22:58 +09002516
2517/*
William Lallemand51097192015-04-14 16:35:22 +02002518 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002519 * Returns the error code, 0 if OK, or any combination of :
2520 * - ERR_ABORT: must abort ASAP
2521 * - ERR_FATAL: we can continue parsing but not start the service
2522 * - ERR_WARN: a warning has been emitted
2523 * - ERR_ALERT: an alert has been emitted
2524 * Only the two first ones can stop processing, the two others are just
2525 * indicators.
2526 */
2527int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2528{
2529 static struct mailers *curmailers = NULL;
2530 struct mailer *newmailer = NULL;
2531 const char *err;
2532 int err_code = 0;
2533 char *errmsg = NULL;
2534
2535 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2536 if (!*args[1]) {
2537 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2538 err_code |= ERR_ALERT | ERR_ABORT;
2539 goto out;
2540 }
2541
2542 err = invalid_char(args[1]);
2543 if (err) {
2544 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2545 file, linenum, *err, args[0], args[1]);
2546 err_code |= ERR_ALERT | ERR_ABORT;
2547 goto out;
2548 }
2549
2550 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2551 /*
2552 * If there are two proxies with the same name only following
2553 * combinations are allowed:
2554 */
2555 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002556 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 +09002557 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002559 }
2560 }
2561
Vincent Bernat02779b62016-04-03 13:48:43 +02002562 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002563 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2564 err_code |= ERR_ALERT | ERR_ABORT;
2565 goto out;
2566 }
2567
2568 curmailers->next = mailers;
2569 mailers = curmailers;
2570 curmailers->conf.file = strdup(file);
2571 curmailers->conf.line = linenum;
2572 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002573 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2574 * But need enough time so that timeouts don't occur
2575 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002576 }
2577 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2578 struct sockaddr_storage *sk;
2579 int port1, port2;
2580 struct protocol *proto;
2581
2582 if (!*args[2]) {
2583 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2584 file, linenum, args[0]);
2585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
2587 }
2588
2589 err = invalid_char(args[1]);
2590 if (err) {
2591 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2592 file, linenum, *err, args[1]);
2593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
2595 }
2596
Vincent Bernat02779b62016-04-03 13:48:43 +02002597 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002598 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2599 err_code |= ERR_ALERT | ERR_ABORT;
2600 goto out;
2601 }
2602
2603 /* the mailers are linked backwards first */
2604 curmailers->count++;
2605 newmailer->next = curmailers->mailer_list;
2606 curmailers->mailer_list = newmailer;
2607 newmailer->mailers = curmailers;
2608 newmailer->conf.file = strdup(file);
2609 newmailer->conf.line = linenum;
2610
2611 newmailer->id = strdup(args[1]);
2612
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002613 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002614 if (!sk) {
2615 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
2618 }
2619
2620 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002621 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2622 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002623 file, linenum, args[0], args[1]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627
2628 if (port1 != port2) {
2629 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2630 file, linenum, args[0], args[1], args[2]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634
2635 if (!port1) {
2636 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2637 file, linenum, args[0], args[1], args[2]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
2642 newmailer->addr = *sk;
2643 newmailer->proto = proto;
2644 newmailer->xprt = &raw_sock;
2645 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002646 }
2647 else if (strcmp(args[0], "timeout") == 0) {
2648 if (!*args[1]) {
2649 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2650 file, linenum, args[0]);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654 else if (strcmp(args[1], "mail") == 0) {
2655 const char *res;
2656 unsigned int timeout_mail;
2657 if (!*args[2]) {
2658 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2659 file, linenum, args[0], args[1]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2664 if (res) {
2665 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2666 file, linenum, *res, args[0]);
2667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
2669 }
2670 if (timeout_mail <= 0) {
2671 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675 curmailers->timeout.mail = timeout_mail;
2676 } else {
2677 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2678 file, linenum, args[0], args[1]);
2679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682 }
Simon Horman0d16a402015-01-30 11:22:58 +09002683 else if (*args[0] != 0) {
2684 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688
2689out:
2690 free(errmsg);
2691 return err_code;
2692}
2693
Simon Horman9dc49962015-01-30 11:22:59 +09002694static void free_email_alert(struct proxy *p)
2695{
2696 free(p->email_alert.mailers.name);
2697 p->email_alert.mailers.name = NULL;
2698 free(p->email_alert.from);
2699 p->email_alert.from = NULL;
2700 free(p->email_alert.to);
2701 p->email_alert.to = NULL;
2702 free(p->email_alert.myhostname);
2703 p->email_alert.myhostname = NULL;
2704}
2705
Willy Tarreau3842f002009-06-14 11:39:52 +02002706int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707{
2708 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002709 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002710 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002711 int rc;
2712 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002713 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002714 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002715 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002716 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002717 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718
Willy Tarreau977b8e42006-12-29 14:19:17 +01002719 if (!strcmp(args[0], "listen"))
2720 rc = PR_CAP_LISTEN;
2721 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002722 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002723 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002724 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002725 else
2726 rc = PR_CAP_NONE;
2727
2728 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 if (!*args[1]) {
2730 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002731 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_ABORT;
2734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002736
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002737 err = invalid_char(args[1]);
2738 if (err) {
2739 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2740 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002742 }
2743
Willy Tarreau8f50b682015-05-26 11:45:02 +02002744 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2745 if (curproxy) {
2746 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2747 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2748 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002750 }
2751
Vincent Bernat02779b62016-04-03 13:48:43 +02002752 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_ABORT;
2755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002757
Willy Tarreau97cb7802010-01-03 20:23:58 +01002758 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 curproxy->next = proxy;
2760 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002761 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2762 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002763 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002765 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002766 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767
William Lallemand6e62fb62015-04-28 16:55:23 +02002768 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2769 if (curproxy->cap & PR_CAP_FE)
2770 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
2773
2774 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002775 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002776 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002777
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002780 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002781 curproxy->no_options = defproxy.no_options;
2782 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002783 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002784 curproxy->except_net = defproxy.except_net;
2785 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002786 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002787 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002789 if (defproxy.fwdfor_hdr_len) {
2790 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2791 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2792 }
2793
Willy Tarreaub86db342009-11-30 11:50:16 +01002794 if (defproxy.orgto_hdr_len) {
2795 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2796 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2797 }
2798
Mark Lamourinec2247f02012-01-04 13:02:01 -05002799 if (defproxy.server_id_hdr_len) {
2800 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2801 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2802 }
2803
Willy Tarreau977b8e42006-12-29 14:19:17 +01002804 if (curproxy->cap & PR_CAP_FE) {
2805 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002806 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002807 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002808
2809 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002810 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2811 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002812
2813 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815
Willy Tarreau977b8e42006-12-29 14:19:17 +01002816 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002817 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002818 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002819 curproxy->fullconn = defproxy.fullconn;
2820 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002821 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002822 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002824 if (defproxy.check_req) {
2825 curproxy->check_req = calloc(1, defproxy.check_len);
2826 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2827 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002830 if (defproxy.expect_str) {
2831 curproxy->expect_str = strdup(defproxy.expect_str);
2832 if (defproxy.expect_regex) {
2833 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002834 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2835 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002836 }
2837 }
2838
Willy Tarreau67402132012-05-31 20:40:20 +02002839 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002840 if (defproxy.cookie_name)
2841 curproxy->cookie_name = strdup(defproxy.cookie_name);
2842 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002843 if (defproxy.cookie_domain)
2844 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002845
Willy Tarreau31936852010-10-06 16:59:56 +02002846 if (defproxy.cookie_maxidle)
2847 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2848
2849 if (defproxy.cookie_maxlife)
2850 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2851
Emeric Brun647caf12009-06-30 17:57:00 +02002852 if (defproxy.rdp_cookie_name)
2853 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2854 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2855
Willy Tarreau01732802007-11-01 22:48:15 +01002856 if (defproxy.url_param_name)
2857 curproxy->url_param_name = strdup(defproxy.url_param_name);
2858 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002859
Benoitaffb4812009-03-25 13:02:10 +01002860 if (defproxy.hh_name)
2861 curproxy->hh_name = strdup(defproxy.hh_name);
2862 curproxy->hh_len = defproxy.hh_len;
2863 curproxy->hh_match_domain = defproxy.hh_match_domain;
2864
Willy Tarreauef9a3602012-12-08 22:29:20 +01002865 if (defproxy.conn_src.iface_name)
2866 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2867 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002868 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002869#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002870 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002871#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002872 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002875 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002876 if (defproxy.capture_name)
2877 curproxy->capture_name = strdup(defproxy.capture_name);
2878 curproxy->capture_namelen = defproxy.capture_namelen;
2879 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002883 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002884 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002885 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002886 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002887 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 curproxy->mon_net = defproxy.mon_net;
2889 curproxy->mon_mask = defproxy.mon_mask;
2890 if (defproxy.monitor_uri)
2891 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2892 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002893 if (defproxy.defbe.name)
2894 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002895
2896 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002897 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2898 if (curproxy->conf.logformat_string &&
2899 curproxy->conf.logformat_string != default_http_log_format &&
2900 curproxy->conf.logformat_string != default_tcp_log_format &&
2901 curproxy->conf.logformat_string != clf_http_log_format)
2902 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2903
2904 if (defproxy.conf.lfs_file) {
2905 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2906 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2907 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002908
2909 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2910 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2911 if (curproxy->conf.logformat_sd_string &&
2912 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2913 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2914
2915 if (defproxy.conf.lfsd_file) {
2916 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2917 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2918 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002919 }
2920
2921 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002922 curproxy->timeout.connect = defproxy.timeout.connect;
2923 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002924 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002925 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002926 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002927 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002928 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002929 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002930 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002931 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 }
2933
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002935 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002936
2937 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002938 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002939 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002940 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002941 LIST_INIT(&node->list);
2942 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2943 }
2944
Willy Tarreau62a61232013-04-12 18:13:46 +02002945 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2946 if (curproxy->conf.uniqueid_format_string)
2947 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2948
Dragan Dosen43885c72015-10-01 13:18:13 +02002949 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002950
Willy Tarreau62a61232013-04-12 18:13:46 +02002951 if (defproxy.conf.uif_file) {
2952 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2953 curproxy->conf.uif_line = defproxy.conf.uif_line;
2954 }
William Lallemanda73203e2012-03-12 12:48:57 +01002955
2956 /* copy default header unique id */
2957 if (defproxy.header_unique_id)
2958 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2959
William Lallemand82fe75c2012-10-23 10:25:10 +02002960 /* default compression options */
2961 if (defproxy.comp != NULL) {
2962 curproxy->comp = calloc(1, sizeof(struct comp));
2963 curproxy->comp->algos = defproxy.comp->algos;
2964 curproxy->comp->types = defproxy.comp->types;
2965 }
2966
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002968 curproxy->conf.used_listener_id = EB_ROOT;
2969 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002970
Simon Horman98637e52014-06-20 12:30:16 +09002971 if (defproxy.check_path)
2972 curproxy->check_path = strdup(defproxy.check_path);
2973 if (defproxy.check_command)
2974 curproxy->check_command = strdup(defproxy.check_command);
2975
Simon Horman9dc49962015-01-30 11:22:59 +09002976 if (defproxy.email_alert.mailers.name)
2977 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2978 if (defproxy.email_alert.from)
2979 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2980 if (defproxy.email_alert.to)
2981 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2982 if (defproxy.email_alert.myhostname)
2983 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002984 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002985 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002986
Willy Tarreau93893792009-07-23 13:19:11 +02002987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
2989 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2990 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002991 /* FIXME-20070101: we should do this too at the end of the
2992 * config parsing to free all default values.
2993 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002994 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2995 err_code |= ERR_ABORT;
2996 goto out;
2997 }
2998
Willy Tarreaua534fea2008-08-03 12:19:50 +02002999 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003000 free(defproxy.check_command);
3001 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003002 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003003 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003004 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003005 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003006 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003007 free(defproxy.capture_name);
3008 free(defproxy.monitor_uri);
3009 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003010 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003011 free(defproxy.fwdfor_hdr_name);
3012 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003013 free(defproxy.orgto_hdr_name);
3014 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003015 free(defproxy.server_id_hdr_name);
3016 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003017 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003018 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003019 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003020 free(defproxy.expect_regex);
3021 defproxy.expect_regex = NULL;
3022 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003023
Willy Tarreau62a61232013-04-12 18:13:46 +02003024 if (defproxy.conf.logformat_string != default_http_log_format &&
3025 defproxy.conf.logformat_string != default_tcp_log_format &&
3026 defproxy.conf.logformat_string != clf_http_log_format)
3027 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003028
Willy Tarreau62a61232013-04-12 18:13:46 +02003029 free(defproxy.conf.uniqueid_format_string);
3030 free(defproxy.conf.lfs_file);
3031 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003032 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003033 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003034
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003035 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3036 free(defproxy.conf.logformat_sd_string);
3037 free(defproxy.conf.lfsd_file);
3038
Willy Tarreaua534fea2008-08-03 12:19:50 +02003039 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003040 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003041
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 /* we cannot free uri_auth because it might already be used */
3043 init_default_instance();
3044 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003045 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3046 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
3050 else if (curproxy == NULL) {
3051 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003055
3056 /* update the current file and line being parsed */
3057 curproxy->conf.args.file = curproxy->conf.file;
3058 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003059
3060 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003061 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3062 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3063 if (err_code & ERR_FATAL)
3064 goto out;
3065 }
3066 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003067 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003068 int cur_arg;
3069
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 if (curproxy == &defproxy) {
3071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077
Willy Tarreau24709282013-03-10 21:32:12 +01003078 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003079 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003084
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003085 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003086
3087 /* use default settings for unix sockets */
3088 bind_conf->ux.uid = global.unix_bind.ux.uid;
3089 bind_conf->ux.gid = global.unix_bind.ux.gid;
3090 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003091
3092 /* NOTE: the following line might create several listeners if there
3093 * are comma-separated IPs or port ranges. So all further processing
3094 * will have to be applied to all listeners created after last_listen.
3095 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003096 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3097 if (errmsg && *errmsg) {
3098 indent_msg(&errmsg, 2);
3099 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003100 }
3101 else
3102 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3103 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003107
Willy Tarreau4348fad2012-09-20 16:48:07 +02003108 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3109 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003110 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003111 }
3112
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003113 cur_arg = 2;
3114 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003115 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003116 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003117 char *err;
3118
Willy Tarreau26982662012-09-12 23:17:10 +02003119 kw = bind_find_kw(args[cur_arg]);
3120 if (kw) {
3121 char *err = NULL;
3122 int code;
3123
3124 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003125 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3126 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003127 cur_arg += 1 + kw->skip ;
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131
Willy Tarreau4348fad2012-09-20 16:48:07 +02003132 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003133 err_code |= code;
3134
3135 if (code) {
3136 if (err && *err) {
3137 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003138 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003139 }
3140 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003141 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3142 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003143 if (code & ERR_FATAL) {
3144 free(err);
3145 cur_arg += 1 + kw->skip;
3146 goto out;
3147 }
3148 }
3149 free(err);
3150 cur_arg += 1 + kw->skip;
3151 continue;
3152 }
3153
Willy Tarreau8638f482012-09-18 18:01:17 +02003154 err = NULL;
3155 if (!bind_dumped) {
3156 bind_dump_kws(&err);
3157 indent_msg(&err, 4);
3158 bind_dumped = 1;
3159 }
3160
3161 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3162 file, linenum, args[0], args[1], args[cur_arg],
3163 err ? " Registered keywords :" : "", err ? err : "");
3164 free(err);
3165
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003168 }
Willy Tarreau93893792009-07-23 13:19:11 +02003169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 }
3171 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003172 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003178 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003180
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 /* flush useless bits */
3182 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003185 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003186 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003188
William Lallemanddf1425a2015-04-28 20:17:49 +02003189 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3190 goto out;
3191
Willy Tarreau1c47f852006-07-09 08:22:27 +02003192 if (!*args[1]) {
3193 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003197 }
3198
Willy Tarreaua534fea2008-08-03 12:19:50 +02003199 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003200 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003201 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003202 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003203 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3204
Willy Tarreau93893792009-07-23 13:19:11 +02003205 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003208 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3209 goto out;
3210
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3212 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3213 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3214 else {
3215 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
3219 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003220 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003221 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003222
3223 if (curproxy == &defproxy) {
3224 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3225 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003228 }
3229
William Lallemanddf1425a2015-04-28 20:17:49 +02003230 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3231 goto out;
3232
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003233 if (!*args[1]) {
3234 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003238 }
3239
3240 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003241 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003242 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003243
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003244 if (curproxy->uuid <= 0) {
3245 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003246 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003249 }
3250
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003251 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3252 if (node) {
3253 struct proxy *target = container_of(node, struct proxy, conf.id);
3254 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3255 file, linenum, proxy_type_str(curproxy), curproxy->id,
3256 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003261 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003262 else if (!strcmp(args[0], "description")) {
3263 int i, len=0;
3264 char *d;
3265
Cyril Bonté99ed3272010-01-24 23:29:44 +01003266 if (curproxy == &defproxy) {
3267 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3268 file, linenum, args[0]);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271 }
3272
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003273 if (!*args[1]) {
3274 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3275 file, linenum, args[0]);
3276 return -1;
3277 }
3278
Willy Tarreau348acfe2014-04-14 15:00:39 +02003279 for (i = 1; *args[i]; i++)
3280 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003281
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003282 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003283 curproxy->desc = d;
3284
Willy Tarreau348acfe2014-04-14 15:00:39 +02003285 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3286 for (i = 2; *args[i]; i++)
3287 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003288
3289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003291 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 curproxy->state = PR_STSTOPPED;
3294 }
3295 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003296 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 curproxy->state = PR_STNEW;
3299 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003300 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3301 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003302 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003303
3304 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003305 unsigned int low, high;
3306
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003307 if (strcmp(args[cur_arg], "all") == 0) {
3308 set = 0;
3309 break;
3310 }
3311 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003312 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003313 }
3314 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003315 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003316 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003317 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003318 char *dash = strchr(args[cur_arg], '-');
3319
3320 low = high = str2uic(args[cur_arg]);
3321 if (dash)
3322 high = str2uic(dash + 1);
3323
3324 if (high < low) {
3325 unsigned int swap = low;
3326 low = high;
3327 high = swap;
3328 }
3329
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003330 if (low < 1 || high > LONGBITS) {
3331 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3332 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003335 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003336 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003337 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003338 }
3339 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003340 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3341 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003344 }
3345 cur_arg++;
3346 }
3347 curproxy->bind_proc = set;
3348 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003349 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003350 if (curproxy == &defproxy) {
3351 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003354 }
3355
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003356 err = invalid_char(args[1]);
3357 if (err) {
3358 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3359 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003361 }
3362
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003363 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003364 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3365 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003368 }
3369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3371 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372
Willy Tarreau977b8e42006-12-29 14:19:17 +01003373 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003374 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003375
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 if (*(args[1]) == 0) {
3377 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3378 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003382
Willy Tarreau67402132012-05-31 20:40:20 +02003383 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003384 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003385 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003386 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 curproxy->cookie_name = strdup(args[1]);
3388 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003389
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 cur_arg = 2;
3391 while (*(args[cur_arg])) {
3392 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003393 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
3395 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003396 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
3398 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003399 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003402 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003405 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003407 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003408 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003411 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003413 else if (!strcmp(args[cur_arg], "httponly")) {
3414 curproxy->ck_opts |= PR_CK_HTTPONLY;
3415 }
3416 else if (!strcmp(args[cur_arg], "secure")) {
3417 curproxy->ck_opts |= PR_CK_SECURE;
3418 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003419 else if (!strcmp(args[cur_arg], "domain")) {
3420 if (!*args[cur_arg + 1]) {
3421 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3422 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003425 }
3426
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003427 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003428 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003429 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3430 " dots nor does not start with a dot."
3431 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003432 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003433 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003434 }
3435
3436 err = invalid_domainchar(args[cur_arg + 1]);
3437 if (err) {
3438 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3439 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003442 }
3443
Willy Tarreau68a897b2009-12-03 23:28:34 +01003444 if (!curproxy->cookie_domain) {
3445 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3446 } else {
3447 /* one domain was already specified, add another one by
3448 * building the string which will be returned along with
3449 * the cookie.
3450 */
3451 char *new_ptr;
3452 int new_len = strlen(curproxy->cookie_domain) +
3453 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3454 new_ptr = malloc(new_len);
3455 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3456 free(curproxy->cookie_domain);
3457 curproxy->cookie_domain = new_ptr;
3458 }
Willy Tarreau31936852010-10-06 16:59:56 +02003459 cur_arg++;
3460 }
3461 else if (!strcmp(args[cur_arg], "maxidle")) {
3462 unsigned int maxidle;
3463 const char *res;
3464
3465 if (!*args[cur_arg + 1]) {
3466 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3467 file, linenum, args[cur_arg]);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
3471
3472 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3473 if (res) {
3474 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3475 file, linenum, *res, args[cur_arg]);
3476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
3478 }
3479 curproxy->cookie_maxidle = maxidle;
3480 cur_arg++;
3481 }
3482 else if (!strcmp(args[cur_arg], "maxlife")) {
3483 unsigned int maxlife;
3484 const char *res;
3485
3486 if (!*args[cur_arg + 1]) {
3487 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3488 file, linenum, args[cur_arg]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492
3493 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3494 if (res) {
3495 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3496 file, linenum, *res, args[cur_arg]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003501 cur_arg++;
3502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003504 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 }
3509 cur_arg++;
3510 }
Willy Tarreau67402132012-05-31 20:40:20 +02003511 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3513 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 }
3516
Willy Tarreau67402132012-05-31 20:40:20 +02003517 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3519 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003522
Willy Tarreau67402132012-05-31 20:40:20 +02003523 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003524 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3525 file, linenum);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003529 else if (!strcmp(args[0], "email-alert")) {
3530 if (*(args[1]) == 0) {
3531 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3532 file, linenum, args[0]);
3533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
3535 }
3536
3537 if (!strcmp(args[1], "from")) {
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.from);
3545 curproxy->email_alert.from = strdup(args[2]);
3546 }
3547 else if (!strcmp(args[1], "mailers")) {
3548 if (*(args[1]) == 0) {
3549 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3550 file, linenum, args[1]);
3551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
3553 }
3554 free(curproxy->email_alert.mailers.name);
3555 curproxy->email_alert.mailers.name = strdup(args[2]);
3556 }
3557 else if (!strcmp(args[1], "myhostname")) {
3558 if (*(args[1]) == 0) {
3559 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3560 file, linenum, args[1]);
3561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
3563 }
3564 free(curproxy->email_alert.myhostname);
3565 curproxy->email_alert.myhostname = strdup(args[2]);
3566 }
Simon Horman64e34162015-02-06 11:11:57 +09003567 else if (!strcmp(args[1], "level")) {
3568 curproxy->email_alert.level = get_log_level(args[2]);
3569 if (curproxy->email_alert.level < 0) {
3570 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3571 file, linenum, args[1], args[2]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
3575 }
Simon Horman9dc49962015-01-30 11:22:59 +09003576 else if (!strcmp(args[1], "to")) {
3577 if (*(args[1]) == 0) {
3578 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3579 file, linenum, args[1]);
3580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
3582 }
3583 free(curproxy->email_alert.to);
3584 curproxy->email_alert.to = strdup(args[2]);
3585 }
3586 else {
3587 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3588 file, linenum, args[1]);
3589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
3591 }
Simon Horman64e34162015-02-06 11:11:57 +09003592 /* Indicate that the email_alert is at least partially configured */
3593 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003594 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003595 else if (!strcmp(args[0], "external-check")) {
3596 if (*(args[1]) == 0) {
3597 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3598 file, linenum, args[0]);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601 }
3602
3603 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003604 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003605 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003606 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003607 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3608 file, linenum, args[1]);
3609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
3611 }
3612 free(curproxy->check_command);
3613 curproxy->check_command = strdup(args[2]);
3614 }
3615 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003616 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003617 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003618 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003619 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3620 file, linenum, args[1]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 free(curproxy->check_path);
3625 curproxy->check_path = strdup(args[2]);
3626 }
3627 else {
3628 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3629 file, linenum, args[1]);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003634 else if (!strcmp(args[0], "persist")) { /* persist */
3635 if (*(args[1]) == 0) {
3636 Alert("parsing [%s:%d] : missing persist method.\n",
3637 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003640 }
3641
3642 if (!strncmp(args[1], "rdp-cookie", 10)) {
3643 curproxy->options2 |= PR_O2_RDPC_PRST;
3644
Emeric Brunb982a3d2010-01-04 15:45:53 +01003645 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003646 const char *beg, *end;
3647
3648 beg = args[1] + 11;
3649 end = strchr(beg, ')');
3650
William Lallemanddf1425a2015-04-28 20:17:49 +02003651 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3652 goto out;
3653
Emeric Brun647caf12009-06-30 17:57:00 +02003654 if (!end || end == beg) {
3655 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3656 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003659 }
3660
3661 free(curproxy->rdp_cookie_name);
3662 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3663 curproxy->rdp_cookie_len = end-beg;
3664 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003665 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003666 free(curproxy->rdp_cookie_name);
3667 curproxy->rdp_cookie_name = strdup("msts");
3668 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3669 }
3670 else { /* syntax */
3671 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3672 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003675 }
3676 }
3677 else {
3678 Alert("parsing [%s:%d] : unknown persist method.\n",
3679 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003682 }
3683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003685 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003689 else if (!strcmp(args[0], "load-server-state-from-file")) {
3690 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3691 err_code |= ERR_WARN;
3692 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3693 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3694 }
3695 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3696 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3697 }
3698 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3699 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3700 }
3701 else {
3702 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3703 file, linenum, args[0], args[1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 }
3708 else if (!strcmp(args[0], "server-state-file-name")) {
3709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3710 err_code |= ERR_WARN;
3711 if (*(args[1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3713 file, linenum, args[0]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 else if (!strcmp(args[1], "use-backend-name"))
3718 curproxy->server_state_file_name = strdup(curproxy->id);
3719 else
3720 curproxy->server_state_file_name = strdup(args[1]);
3721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003723 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003725
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003727 if (curproxy == &defproxy) {
3728 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732
William Lallemand1a748ae2015-05-19 16:37:23 +02003733 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3734 goto out;
3735
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 if (*(args[4]) == 0) {
3737 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003742 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 curproxy->capture_name = strdup(args[2]);
3744 curproxy->capture_namelen = strlen(curproxy->capture_name);
3745 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 curproxy->to_log |= LW_COOKIE;
3747 }
3748 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3749 struct cap_hdr *hdr;
3750
3751 if (curproxy == &defproxy) {
3752 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 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 }
3756
William Lallemand1a748ae2015-05-19 16:37:23 +02003757 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3758 goto out;
3759
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3761 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3762 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 }
3766
Vincent Bernat02779b62016-04-03 13:48:43 +02003767 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 hdr->next = curproxy->req_cap;
3769 hdr->name = strdup(args[3]);
3770 hdr->namelen = strlen(args[3]);
3771 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003772 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 hdr->index = curproxy->nb_req_cap++;
3774 curproxy->req_cap = hdr;
3775 curproxy->to_log |= LW_REQHDR;
3776 }
3777 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3778 struct cap_hdr *hdr;
3779
3780 if (curproxy == &defproxy) {
3781 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 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
3785
William Lallemand1a748ae2015-05-19 16:37:23 +02003786 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3787 goto out;
3788
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3790 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003795 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 hdr->next = curproxy->rsp_cap;
3797 hdr->name = strdup(args[3]);
3798 hdr->namelen = strlen(args[3]);
3799 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003800 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 hdr->index = curproxy->nb_rsp_cap++;
3802 curproxy->rsp_cap = hdr;
3803 curproxy->to_log |= LW_RSPHDR;
3804 }
3805 else {
3806 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3807 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003813 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003815
William Lallemanddf1425a2015-04-28 20:17:49 +02003816 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3817 goto out;
3818
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 if (*(args[1]) == 0) {
3820 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
3825 curproxy->conn_retries = atol(args[1]);
3826 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003827 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003828 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003829
3830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
Willy Tarreau20b0de52012-12-24 15:45:22 +01003836 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003837 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003838 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3839 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3840 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3841 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003842 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 +01003843 file, linenum, args[0]);
3844 err_code |= ERR_WARN;
3845 }
3846
Willy Tarreauff011f22011-01-06 17:51:27 +01003847 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003848
Willy Tarreauff011f22011-01-06 17:51:27 +01003849 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003850 err_code |= ERR_ALERT | ERR_ABORT;
3851 goto out;
3852 }
3853
Willy Tarreau5002f572014-04-23 01:32:02 +02003854 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003855 err_code |= warnif_cond_conflicts(rule->cond,
3856 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3857 file, linenum);
3858
Willy Tarreauff011f22011-01-06 17:51:27 +01003859 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003860 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003861 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003862 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003863
3864 if (curproxy == &defproxy) {
3865 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869
3870 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003871 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003872 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3873 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003874 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3875 file, linenum, args[0]);
3876 err_code |= ERR_WARN;
3877 }
3878
3879 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3880
3881 if (!rule) {
3882 err_code |= ERR_ALERT | ERR_ABORT;
3883 goto out;
3884 }
3885
3886 err_code |= warnif_cond_conflicts(rule->cond,
3887 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3888 file, linenum);
3889
3890 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3891 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003892 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3893 /* set the header name and length into the proxy structure */
3894 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3895 err_code |= ERR_WARN;
3896
3897 if (!*args[1]) {
3898 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3899 file, linenum, args[0]);
3900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
3902 }
3903
3904 /* set the desired header name */
3905 free(curproxy->server_id_hdr_name);
3906 curproxy->server_id_hdr_name = strdup(args[1]);
3907 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3908 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003909 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003910 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003911
Willy Tarreaub099aca2008-10-12 17:26:37 +02003912 if (curproxy == &defproxy) {
3913 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003916 }
3917
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003918 /* emulate "block" using "http-request block". Since these rules are supposed to
3919 * be processed before all http-request rules, we put them into their own list
3920 * and will insert them at the end.
3921 */
3922 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3923 if (!rule) {
3924 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003925 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003926 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003927 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3928 err_code |= warnif_cond_conflicts(rule->cond,
3929 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3930 file, linenum);
3931 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003932
3933 if (!already_warned(WARN_BLOCK_DEPRECATED))
3934 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]);
3935
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003936 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003937 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003938 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003939
Cyril Bonté99ed3272010-01-24 23:29:44 +01003940 if (curproxy == &defproxy) {
3941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
3945
Willy Tarreaube4653b2015-05-28 15:26:58 +02003946 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003947 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3948 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003951 }
3952
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003953 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003954 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003955 err_code |= warnif_cond_conflicts(rule->cond,
3956 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3957 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003958 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003959 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003960 struct switching_rule *rule;
3961
Willy Tarreaub099aca2008-10-12 17:26:37 +02003962 if (curproxy == &defproxy) {
3963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003966 }
3967
Willy Tarreau55ea7572007-06-17 19:56:27 +02003968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003970
3971 if (*(args[1]) == 0) {
3972 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003975 }
3976
Willy Tarreauf51658d2014-04-23 01:21:56 +02003977 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3978 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3979 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3980 file, linenum, errmsg);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003984
Willy Tarreauf51658d2014-04-23 01:21:56 +02003985 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003986 }
3987
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003988 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003989 if (!rule) {
3990 Alert("Out of memory error.\n");
3991 goto out;
3992 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003993 rule->cond = cond;
3994 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003995 rule->line = linenum;
3996 rule->file = strdup(file);
3997 if (!rule->file) {
3998 Alert("Out of memory error.\n");
3999 goto out;
4000 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004001 LIST_INIT(&rule->list);
4002 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4003 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004004 else if (strcmp(args[0], "use-server") == 0) {
4005 struct server_rule *rule;
4006
4007 if (curproxy == &defproxy) {
4008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012
4013 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4014 err_code |= ERR_WARN;
4015
4016 if (*(args[1]) == 0) {
4017 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4023 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4024 file, linenum, args[0]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004029 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4030 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4031 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004036 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004037
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004038 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004039 rule->cond = cond;
4040 rule->srv.name = strdup(args[1]);
4041 LIST_INIT(&rule->list);
4042 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4043 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4044 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004045 else if ((!strcmp(args[0], "force-persist")) ||
4046 (!strcmp(args[0], "ignore-persist"))) {
4047 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004048
4049 if (curproxy == &defproxy) {
4050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
4055 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4056 err_code |= ERR_WARN;
4057
Willy Tarreauef6494c2010-01-28 17:12:36 +01004058 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004059 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4060 file, linenum, args[0]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004065 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4066 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4067 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
4070 }
4071
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004072 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4073 * where force-persist is applied.
4074 */
4075 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004076
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004077 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004078 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004079 if (!strcmp(args[0], "force-persist")) {
4080 rule->type = PERSIST_TYPE_FORCE;
4081 } else {
4082 rule->type = PERSIST_TYPE_IGNORE;
4083 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004084 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004085 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004086 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004087 else if (!strcmp(args[0], "stick-table")) {
4088 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004089 struct proxy *other;
4090
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004091 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004092 if (other) {
4093 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4094 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004098
Emeric Brun32da3c42010-09-23 18:39:19 +02004099 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004100 curproxy->table.type = (unsigned int)-1;
4101 while (*args[myidx]) {
4102 const char *err;
4103
4104 if (strcmp(args[myidx], "size") == 0) {
4105 myidx++;
4106 if (!*(args[myidx])) {
4107 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4108 file, linenum, args[myidx-1]);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111 }
4112 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4113 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4114 file, linenum, *err, args[myidx-1]);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004118 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004119 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004120 else if (strcmp(args[myidx], "peers") == 0) {
4121 myidx++;
Godbach50523162013-12-11 19:48:57 +08004122 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004123 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4124 file, linenum, args[myidx-1]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Godbach50523162013-12-11 19:48:57 +08004127 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004128 curproxy->table.peers.name = strdup(args[myidx++]);
4129 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 else if (strcmp(args[myidx], "expire") == 0) {
4131 myidx++;
4132 if (!*(args[myidx])) {
4133 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4134 file, linenum, args[myidx-1]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
4138 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4139 if (err) {
4140 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4141 file, linenum, *err, args[myidx-1]);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004145 if (val > INT_MAX) {
4146 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4147 file, linenum, val);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004151 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004152 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004153 }
4154 else if (strcmp(args[myidx], "nopurge") == 0) {
4155 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004156 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004157 }
4158 else if (strcmp(args[myidx], "type") == 0) {
4159 myidx++;
4160 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4161 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4162 file, linenum, args[myidx]);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004166 /* myidx already points to next arg */
4167 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004168 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004169 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004170 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004171
4172 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004173 nw = args[myidx];
4174 while (*nw) {
4175 /* the "store" keyword supports a comma-separated list */
4176 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004177 sa = NULL; /* store arg */
4178 while (*nw && *nw != ',') {
4179 if (*nw == '(') {
4180 *nw = 0;
4181 sa = ++nw;
4182 while (*nw != ')') {
4183 if (!*nw) {
4184 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4185 file, linenum, args[0], cw);
4186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
4188 }
4189 nw++;
4190 }
4191 *nw = '\0';
4192 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004193 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004194 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004195 if (*nw)
4196 *nw++ = '\0';
4197 type = stktable_get_data_type(cw);
4198 if (type < 0) {
4199 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4200 file, linenum, args[0], cw);
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
Willy Tarreauac782882010-06-20 10:41:54 +02004204
4205 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4206 switch (err) {
4207 case PE_NONE: break;
4208 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004209 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4210 file, linenum, args[0], cw);
4211 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004212 break;
4213
4214 case PE_ARG_MISSING:
4215 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4216 file, linenum, args[0], cw);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219
4220 case PE_ARG_NOT_USED:
4221 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4222 file, linenum, args[0], cw);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225
4226 default:
4227 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4228 file, linenum, args[0], cw);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004231 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004232 }
4233 myidx++;
4234 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004235 else {
4236 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4237 file, linenum, args[myidx]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004240 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 }
4242
4243 if (!curproxy->table.size) {
4244 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4245 file, linenum);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
4250 if (curproxy->table.type == (unsigned int)-1) {
4251 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4252 file, linenum);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256 }
4257 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004258 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004259 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004260 int myidx = 0;
4261 const char *name = NULL;
4262 int flags;
4263
4264 if (curproxy == &defproxy) {
4265 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
4270 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4271 err_code |= ERR_WARN;
4272 goto out;
4273 }
4274
4275 myidx++;
4276 if ((strcmp(args[myidx], "store") == 0) ||
4277 (strcmp(args[myidx], "store-request") == 0)) {
4278 myidx++;
4279 flags = STK_IS_STORE;
4280 }
4281 else if (strcmp(args[myidx], "store-response") == 0) {
4282 myidx++;
4283 flags = STK_IS_STORE | STK_ON_RSP;
4284 }
4285 else if (strcmp(args[myidx], "match") == 0) {
4286 myidx++;
4287 flags = STK_IS_MATCH;
4288 }
4289 else if (strcmp(args[myidx], "on") == 0) {
4290 myidx++;
4291 flags = STK_IS_MATCH | STK_IS_STORE;
4292 }
4293 else {
4294 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298
4299 if (*(args[myidx]) == 0) {
4300 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004305 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004306 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004307 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004308 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312
4313 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004314 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4315 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4316 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004317 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004318 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004319 goto out;
4320 }
4321 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004322 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4323 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4324 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004325 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004326 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004327 goto out;
4328 }
4329 }
4330
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004331 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004332 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004333
Emeric Brunb982a3d2010-01-04 15:45:53 +01004334 if (strcmp(args[myidx], "table") == 0) {
4335 myidx++;
4336 name = args[myidx++];
4337 }
4338
Willy Tarreauef6494c2010-01-28 17:12:36 +01004339 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004340 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4341 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4342 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004343 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004344 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004345 goto out;
4346 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004347 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004348 else if (*(args[myidx])) {
4349 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4350 file, linenum, args[0], args[myidx]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004352 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004353 goto out;
4354 }
Emeric Brun97679e72010-09-23 17:56:44 +02004355 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004356 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004357 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004358 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004359
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004360 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004361 rule->cond = cond;
4362 rule->expr = expr;
4363 rule->flags = flags;
4364 rule->table.name = name ? strdup(name) : NULL;
4365 LIST_INIT(&rule->list);
4366 if (flags & STK_ON_RSP)
4367 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4368 else
4369 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 else if (!strcmp(args[0], "stats")) {
4372 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4373 curproxy->uri_auth = NULL; /* we must detach from the default config */
4374
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004375 if (!*args[1]) {
4376 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004377 } else if (!strcmp(args[1], "admin")) {
4378 struct stats_admin_rule *rule;
4379
4380 if (curproxy == &defproxy) {
4381 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
4384 }
4385
4386 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4387 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4388 err_code |= ERR_ALERT | ERR_ABORT;
4389 goto out;
4390 }
4391
4392 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4393 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4394 file, linenum, args[0], args[1]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004398 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4399 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4400 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
4403 }
4404
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004405 err_code |= warnif_cond_conflicts(cond,
4406 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4407 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004408
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004409 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004410 rule->cond = cond;
4411 LIST_INIT(&rule->list);
4412 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 } else if (!strcmp(args[1], "uri")) {
4414 if (*(args[2]) == 0) {
4415 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4419 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_ABORT;
4421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
4423 } else if (!strcmp(args[1], "realm")) {
4424 if (*(args[2]) == 0) {
4425 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4429 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004430 err_code |= ERR_ALERT | ERR_ABORT;
4431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004433 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004434 unsigned interval;
4435
4436 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4437 if (err) {
4438 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4439 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004442 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4443 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_ABORT;
4445 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004446 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004447 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004448 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004449
4450 if (curproxy == &defproxy) {
4451 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
4454 }
4455
4456 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4457 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4458 err_code |= ERR_ALERT | ERR_ABORT;
4459 goto out;
4460 }
4461
Willy Tarreauff011f22011-01-06 17:51:27 +01004462 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004463 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004464 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4465 file, linenum, args[0]);
4466 err_code |= ERR_WARN;
4467 }
4468
Willy Tarreauff011f22011-01-06 17:51:27 +01004469 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004470
Willy Tarreauff011f22011-01-06 17:51:27 +01004471 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004472 err_code |= ERR_ALERT | ERR_ABORT;
4473 goto out;
4474 }
4475
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004476 err_code |= warnif_cond_conflicts(rule->cond,
4477 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4478 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004479 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004480
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 } else if (!strcmp(args[1], "auth")) {
4482 if (*(args[2]) == 0) {
4483 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_ABORT;
4489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
4491 } else if (!strcmp(args[1], "scope")) {
4492 if (*(args[2]) == 0) {
4493 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4497 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004498 err_code |= ERR_ALERT | ERR_ABORT;
4499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 }
4501 } else if (!strcmp(args[1], "enable")) {
4502 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_ABORT;
4505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004507 } else if (!strcmp(args[1], "hide-version")) {
4508 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_ABORT;
4511 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004512 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004513 } else if (!strcmp(args[1], "show-legends")) {
4514 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4515 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4516 err_code |= ERR_ALERT | ERR_ABORT;
4517 goto out;
4518 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004519 } else if (!strcmp(args[1], "show-node")) {
4520
4521 if (*args[2]) {
4522 int i;
4523 char c;
4524
4525 for (i=0; args[2][i]; i++) {
4526 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004527 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4528 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004529 break;
4530 }
4531
4532 if (!i || args[2][i]) {
4533 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4534 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4535 file, linenum, args[0], args[1]);
4536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
4538 }
4539 }
4540
4541 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4542 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4543 err_code |= ERR_ALERT | ERR_ABORT;
4544 goto out;
4545 }
4546 } else if (!strcmp(args[1], "show-desc")) {
4547 char *desc = NULL;
4548
4549 if (*args[2]) {
4550 int i, len=0;
4551 char *d;
4552
Willy Tarreau348acfe2014-04-14 15:00:39 +02004553 for (i = 2; *args[i]; i++)
4554 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004555
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004556 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004557
Willy Tarreau348acfe2014-04-14 15:00:39 +02004558 d += snprintf(d, desc + len - d, "%s", args[2]);
4559 for (i = 3; *args[i]; i++)
4560 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004561 }
4562
4563 if (!*args[2] && !global.desc)
4564 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4565 file, linenum, args[1]);
4566 else {
4567 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4568 free(desc);
4569 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4570 err_code |= ERR_ALERT | ERR_ABORT;
4571 goto out;
4572 }
4573 free(desc);
4574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004576stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004577 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 +01004578 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 }
4582 }
4583 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004584 int optnum;
4585
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004586 if (*(args[1]) == '\0') {
4587 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004592
4593 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4594 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004595 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4596 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4597 file, linenum, cfg_opts[optnum].name);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004601 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4602 goto out;
4603
Willy Tarreau93893792009-07-23 13:19:11 +02004604 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4605 err_code |= ERR_WARN;
4606 goto out;
4607 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004608
Willy Tarreau3842f002009-06-14 11:39:52 +02004609 curproxy->no_options &= ~cfg_opts[optnum].val;
4610 curproxy->options &= ~cfg_opts[optnum].val;
4611
4612 switch (kwm) {
4613 case KWM_STD:
4614 curproxy->options |= cfg_opts[optnum].val;
4615 break;
4616 case KWM_NO:
4617 curproxy->no_options |= cfg_opts[optnum].val;
4618 break;
4619 case KWM_DEF: /* already cleared */
4620 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004621 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004622
Willy Tarreau93893792009-07-23 13:19:11 +02004623 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004624 }
4625 }
4626
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004627 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4628 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004629 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4630 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4631 file, linenum, cfg_opts2[optnum].name);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004635 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4636 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004637 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4638 err_code |= ERR_WARN;
4639 goto out;
4640 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004641
Willy Tarreau3842f002009-06-14 11:39:52 +02004642 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4643 curproxy->options2 &= ~cfg_opts2[optnum].val;
4644
4645 switch (kwm) {
4646 case KWM_STD:
4647 curproxy->options2 |= cfg_opts2[optnum].val;
4648 break;
4649 case KWM_NO:
4650 curproxy->no_options2 |= cfg_opts2[optnum].val;
4651 break;
4652 case KWM_DEF: /* already cleared */
4653 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004654 }
Willy Tarreau93893792009-07-23 13:19:11 +02004655 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004656 }
4657 }
4658
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004659 /* HTTP options override each other. They can be cancelled using
4660 * "no option xxx" which only switches to default mode if the mode
4661 * was this one (useful for cancelling options set in defaults
4662 * sections).
4663 */
4664 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004665 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4666 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004667 if (kwm == KWM_STD) {
4668 curproxy->options &= ~PR_O_HTTP_MODE;
4669 curproxy->options |= PR_O_HTTP_PCL;
4670 goto out;
4671 }
4672 else if (kwm == KWM_NO) {
4673 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4674 curproxy->options &= ~PR_O_HTTP_MODE;
4675 goto out;
4676 }
4677 }
4678 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004679 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4680 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004681 if (kwm == KWM_STD) {
4682 curproxy->options &= ~PR_O_HTTP_MODE;
4683 curproxy->options |= PR_O_HTTP_FCL;
4684 goto out;
4685 }
4686 else if (kwm == KWM_NO) {
4687 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4688 curproxy->options &= ~PR_O_HTTP_MODE;
4689 goto out;
4690 }
4691 }
4692 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004693 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4694 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004695 if (kwm == KWM_STD) {
4696 curproxy->options &= ~PR_O_HTTP_MODE;
4697 curproxy->options |= PR_O_HTTP_SCL;
4698 goto out;
4699 }
4700 else if (kwm == KWM_NO) {
4701 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4702 curproxy->options &= ~PR_O_HTTP_MODE;
4703 goto out;
4704 }
4705 }
4706 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004707 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4708 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004709 if (kwm == KWM_STD) {
4710 curproxy->options &= ~PR_O_HTTP_MODE;
4711 curproxy->options |= PR_O_HTTP_KAL;
4712 goto out;
4713 }
4714 else if (kwm == KWM_NO) {
4715 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4716 curproxy->options &= ~PR_O_HTTP_MODE;
4717 goto out;
4718 }
4719 }
4720 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004721 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4722 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004723 if (kwm == KWM_STD) {
4724 curproxy->options &= ~PR_O_HTTP_MODE;
4725 curproxy->options |= PR_O_HTTP_TUN;
4726 goto out;
4727 }
4728 else if (kwm == KWM_NO) {
4729 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4730 curproxy->options &= ~PR_O_HTTP_MODE;
4731 goto out;
4732 }
4733 }
4734
Joseph Lynch726ab712015-05-11 23:25:34 -07004735 /* Redispatch can take an integer argument that control when the
4736 * resispatch occurs. All values are relative to the retries option.
4737 * This can be cancelled using "no option xxx".
4738 */
4739 if (strcmp(args[1], "redispatch") == 0) {
4740 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4741 err_code |= ERR_WARN;
4742 goto out;
4743 }
4744
4745 curproxy->no_options &= ~PR_O_REDISP;
4746 curproxy->options &= ~PR_O_REDISP;
4747
4748 switch (kwm) {
4749 case KWM_STD:
4750 curproxy->options |= PR_O_REDISP;
4751 curproxy->redispatch_after = -1;
4752 if(*args[2]) {
4753 curproxy->redispatch_after = atol(args[2]);
4754 }
4755 break;
4756 case KWM_NO:
4757 curproxy->no_options |= PR_O_REDISP;
4758 curproxy->redispatch_after = 0;
4759 break;
4760 case KWM_DEF: /* already cleared */
4761 break;
4762 }
4763 goto out;
4764 }
4765
Willy Tarreau3842f002009-06-14 11:39:52 +02004766 if (kwm != KWM_STD) {
4767 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004768 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004771 }
4772
Emeric Brun3a058f32009-06-30 18:26:00 +02004773 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004774 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004776 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004777 if (*(args[2]) != '\0') {
4778 if (!strcmp(args[2], "clf")) {
4779 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004780 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004781 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004782 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004785 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004786 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4787 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004788 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004789 if (curproxy->conf.logformat_string != default_http_log_format &&
4790 curproxy->conf.logformat_string != default_tcp_log_format &&
4791 curproxy->conf.logformat_string != clf_http_log_format)
4792 free(curproxy->conf.logformat_string);
4793 curproxy->conf.logformat_string = logformat;
4794
4795 free(curproxy->conf.lfs_file);
4796 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4797 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004798 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004799 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004801 if (curproxy->conf.logformat_string != default_http_log_format &&
4802 curproxy->conf.logformat_string != default_tcp_log_format &&
4803 curproxy->conf.logformat_string != clf_http_log_format)
4804 free(curproxy->conf.logformat_string);
4805 curproxy->conf.logformat_string = default_tcp_log_format;
4806
4807 free(curproxy->conf.lfs_file);
4808 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4809 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004810
4811 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4812 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004815 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004816 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004818
William Lallemanddf1425a2015-04-28 20:17:49 +02004819 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4820 goto out;
4821
Willy Tarreau13943ab2006-12-31 00:24:10 +01004822 if (curproxy->cap & PR_CAP_FE)
4823 curproxy->options |= PR_O_TCP_CLI_KA;
4824 if (curproxy->cap & PR_CAP_BE)
4825 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_WARN;
4830
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004832 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004833 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004834 curproxy->options2 &= ~PR_O2_CHK_ANY;
4835 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 if (!*args[2]) { /* no argument */
4837 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4838 curproxy->check_len = strlen(DEF_CHECK_REQ);
4839 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004840 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004841 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004843 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004844 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004845 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 if (*args[4])
4847 reqlen += strlen(args[4]);
4848 else
4849 reqlen += strlen("HTTP/1.0");
4850
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004851 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004853 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004855 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4856 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004857 }
4858 else if (!strcmp(args[1], "ssl-hello-chk")) {
4859 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004862
Willy Tarreaua534fea2008-08-03 12:19:50 +02004863 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004864 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004865 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004866 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004867
4868 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreau23677902007-05-08 23:50:35 +02004871 else if (!strcmp(args[1], "smtpchk")) {
4872 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004873 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004874 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004875 curproxy->options2 &= ~PR_O2_CHK_ANY;
4876 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004877
4878 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4879 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4880 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4881 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4882 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4883 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004884 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004885 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4886 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4887 } else {
4888 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4889 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4890 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4891 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4892 }
4893 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004894 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4895 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004896 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004897 else if (!strcmp(args[1], "pgsql-check")) {
4898 /* use PostgreSQL request to check servers' health */
4899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4900 err_code |= ERR_WARN;
4901
4902 free(curproxy->check_req);
4903 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004904 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004905 curproxy->options2 |= PR_O2_PGSQL_CHK;
4906
4907 if (*(args[2])) {
4908 int cur_arg = 2;
4909
4910 while (*(args[cur_arg])) {
4911 if (strcmp(args[cur_arg], "user") == 0) {
4912 char * packet;
4913 uint32_t packet_len;
4914 uint32_t pv;
4915
4916 /* suboption header - needs additional argument for it */
4917 if (*(args[cur_arg+1]) == 0) {
4918 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4919 file, linenum, args[0], args[1], args[cur_arg]);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923
4924 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4925 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4926 pv = htonl(0x30000); /* protocol version 3.0 */
4927
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004928 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004929
4930 memcpy(packet + 4, &pv, 4);
4931
4932 /* copy "user" */
4933 memcpy(packet + 8, "user", 4);
4934
4935 /* copy username */
4936 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4937
4938 free(curproxy->check_req);
4939 curproxy->check_req = packet;
4940 curproxy->check_len = packet_len;
4941
4942 packet_len = htonl(packet_len);
4943 memcpy(packet, &packet_len, 4);
4944 cur_arg += 2;
4945 } else {
4946 /* unknown suboption - catchall */
4947 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4948 file, linenum, args[0], args[1]);
4949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951 }
4952 } /* end while loop */
4953 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004954 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4955 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004956 }
4957
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004958 else if (!strcmp(args[1], "redis-check")) {
4959 /* use REDIS PING request to check servers' health */
4960 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4961 err_code |= ERR_WARN;
4962
4963 free(curproxy->check_req);
4964 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004965 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004966 curproxy->options2 |= PR_O2_REDIS_CHK;
4967
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004968 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004969 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4970 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004971
4972 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4973 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004974 }
4975
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004976 else if (!strcmp(args[1], "mysql-check")) {
4977 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004978 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4979 err_code |= ERR_WARN;
4980
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004981 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004982 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004983 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004984 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004985
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004986 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004987 * const char mysql40_client_auth_pkt[] = {
4988 * "\x0e\x00\x00" // packet length
4989 * "\x01" // packet number
4990 * "\x00\x00" // client capabilities
4991 * "\x00\x00\x01" // max packet
4992 * "haproxy\x00" // username (null terminated string)
4993 * "\x00" // filler (always 0x00)
4994 * "\x01\x00\x00" // packet length
4995 * "\x00" // packet number
4996 * "\x01" // COM_QUIT command
4997 * };
4998 */
4999
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005000 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5001 * const char mysql41_client_auth_pkt[] = {
5002 * "\x0e\x00\x00\" // packet length
5003 * "\x01" // packet number
5004 * "\x00\x00\x00\x00" // client capabilities
5005 * "\x00\x00\x00\x01" // max packet
5006 * "\x21" // character set (UTF-8)
5007 * char[23] // All zeroes
5008 * "haproxy\x00" // username (null terminated string)
5009 * "\x00" // filler (always 0x00)
5010 * "\x01\x00\x00" // packet length
5011 * "\x00" // packet number
5012 * "\x01" // COM_QUIT command
5013 * };
5014 */
5015
5016
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005017 if (*(args[2])) {
5018 int cur_arg = 2;
5019
5020 while (*(args[cur_arg])) {
5021 if (strcmp(args[cur_arg], "user") == 0) {
5022 char *mysqluser;
5023 int packetlen, reqlen, userlen;
5024
5025 /* suboption header - needs additional argument for it */
5026 if (*(args[cur_arg+1]) == 0) {
5027 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5028 file, linenum, args[0], args[1], args[cur_arg]);
5029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
5031 }
5032 mysqluser = args[cur_arg + 1];
5033 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005034
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005035 if (*(args[cur_arg+2])) {
5036 if (!strcmp(args[cur_arg+2], "post-41")) {
5037 packetlen = userlen + 7 + 27;
5038 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005039
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005040 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005041 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005042 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005043
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005044 snprintf(curproxy->check_req, 4, "%c%c%c",
5045 ((unsigned char) packetlen & 0xff),
5046 ((unsigned char) (packetlen >> 8) & 0xff),
5047 ((unsigned char) (packetlen >> 16) & 0xff));
5048
5049 curproxy->check_req[3] = 1;
5050 curproxy->check_req[5] = 130;
5051 curproxy->check_req[11] = 1;
5052 curproxy->check_req[12] = 33;
5053 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5054 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5055 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5056 cur_arg += 3;
5057 } else {
5058 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
5061 }
5062 } else {
5063 packetlen = userlen + 7;
5064 reqlen = packetlen + 9;
5065
5066 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005067 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005068 curproxy->check_len = reqlen;
5069
5070 snprintf(curproxy->check_req, 4, "%c%c%c",
5071 ((unsigned char) packetlen & 0xff),
5072 ((unsigned char) (packetlen >> 8) & 0xff),
5073 ((unsigned char) (packetlen >> 16) & 0xff));
5074
5075 curproxy->check_req[3] = 1;
5076 curproxy->check_req[5] = 128;
5077 curproxy->check_req[8] = 1;
5078 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5079 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5080 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5081 cur_arg += 2;
5082 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005083 } else {
5084 /* unknown suboption - catchall */
5085 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5086 file, linenum, args[0], args[1]);
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
5090 } /* end while loop */
5091 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005092 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005093 else if (!strcmp(args[1], "ldap-check")) {
5094 /* use LDAP request to check servers' health */
5095 free(curproxy->check_req);
5096 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005097 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005098 curproxy->options2 |= PR_O2_LDAP_CHK;
5099
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005100 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005101 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5102 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005103 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5104 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005105 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005106 else if (!strcmp(args[1], "spop-check")) {
5107 if (curproxy == &defproxy) {
5108 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5109 file, linenum, args[0], args[1]);
5110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
5113 if (curproxy->cap & PR_CAP_FE) {
5114 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5115 file, linenum, args[0], args[1]);
5116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
5118 }
5119
5120 /* use SPOE request to check servers' health */
5121 free(curproxy->check_req);
5122 curproxy->check_req = NULL;
5123 curproxy->options2 &= ~PR_O2_CHK_ANY;
5124 curproxy->options2 |= PR_O2_SPOP_CHK;
5125
5126 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5127 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5132 goto out;
5133 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005134 else if (!strcmp(args[1], "tcp-check")) {
5135 /* use raw TCPCHK send/expect to check servers' health */
5136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5137 err_code |= ERR_WARN;
5138
5139 free(curproxy->check_req);
5140 curproxy->check_req = NULL;
5141 curproxy->options2 &= ~PR_O2_CHK_ANY;
5142 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005143 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5144 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005145 }
Simon Horman98637e52014-06-20 12:30:16 +09005146 else if (!strcmp(args[1], "external-check")) {
5147 /* excute an external command to check servers' health */
5148 free(curproxy->check_req);
5149 curproxy->check_req = NULL;
5150 curproxy->options2 &= ~PR_O2_CHK_ANY;
5151 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005152 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5153 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005154 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005155 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005156 int cur_arg;
5157
5158 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5159 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005160 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005161
Willy Tarreau87cf5142011-08-19 22:57:24 +02005162 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005163
5164 free(curproxy->fwdfor_hdr_name);
5165 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5166 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5167
5168 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5169 cur_arg = 2;
5170 while (*(args[cur_arg])) {
5171 if (!strcmp(args[cur_arg], "except")) {
5172 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005173 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005174 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5175 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005178 }
5179 /* flush useless bits */
5180 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005181 cur_arg += 2;
5182 } else if (!strcmp(args[cur_arg], "header")) {
5183 /* suboption header - needs additional argument for it */
5184 if (*(args[cur_arg+1]) == 0) {
5185 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5186 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005189 }
5190 free(curproxy->fwdfor_hdr_name);
5191 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5192 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5193 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005194 } else if (!strcmp(args[cur_arg], "if-none")) {
5195 curproxy->options &= ~PR_O_FF_ALWAYS;
5196 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005197 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005198 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005199 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005200 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005203 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005204 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005205 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005206 else if (!strcmp(args[1], "originalto")) {
5207 int cur_arg;
5208
5209 /* insert x-original-to field, but not for the IP address listed as an except.
5210 * set default options (ie: bitfield, header name, etc)
5211 */
5212
5213 curproxy->options |= PR_O_ORGTO;
5214
5215 free(curproxy->orgto_hdr_name);
5216 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5217 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5218
Willy Tarreau87cf5142011-08-19 22:57:24 +02005219 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005220 cur_arg = 2;
5221 while (*(args[cur_arg])) {
5222 if (!strcmp(args[cur_arg], "except")) {
5223 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005224 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 +02005225 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5226 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005229 }
5230 /* flush useless bits */
5231 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5232 cur_arg += 2;
5233 } else if (!strcmp(args[cur_arg], "header")) {
5234 /* suboption header - needs additional argument for it */
5235 if (*(args[cur_arg+1]) == 0) {
5236 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5237 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005240 }
5241 free(curproxy->orgto_hdr_name);
5242 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5243 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5244 cur_arg += 2;
5245 } else {
5246 /* unknown suboption - catchall */
5247 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5248 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005251 }
5252 } /* end while loop */
5253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 else {
5255 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
Willy Tarreau93893792009-07-23 13:19:11 +02005259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005261 else if (!strcmp(args[0], "default_backend")) {
5262 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005264
5265 if (*(args[1]) == 0) {
5266 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005269 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005270 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005271 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005272
5273 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5274 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005279
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005280 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5281 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 +01005282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005283 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 /* enable reconnections to dispatch */
5285 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005286
5287 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005290 else if (!strcmp(args[0], "http-reuse")) {
5291 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5292 err_code |= ERR_WARN;
5293
5294 if (strcmp(args[1], "never") == 0) {
5295 /* enable a graceful server shutdown on an HTTP 404 response */
5296 curproxy->options &= ~PR_O_REUSE_MASK;
5297 curproxy->options |= PR_O_REUSE_NEVR;
5298 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5299 goto out;
5300 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005301 else if (strcmp(args[1], "safe") == 0) {
5302 /* enable a graceful server shutdown on an HTTP 404 response */
5303 curproxy->options &= ~PR_O_REUSE_MASK;
5304 curproxy->options |= PR_O_REUSE_SAFE;
5305 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5306 goto out;
5307 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005308 else if (strcmp(args[1], "aggressive") == 0) {
5309 curproxy->options &= ~PR_O_REUSE_MASK;
5310 curproxy->options |= PR_O_REUSE_AGGR;
5311 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5312 goto out;
5313 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005314 else if (strcmp(args[1], "always") == 0) {
5315 /* enable a graceful server shutdown on an HTTP 404 response */
5316 curproxy->options &= ~PR_O_REUSE_MASK;
5317 curproxy->options |= PR_O_REUSE_ALWS;
5318 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5319 goto out;
5320 }
5321 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005322 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005327 else if (!strcmp(args[0], "http-check")) {
5328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005329 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005330
5331 if (strcmp(args[1], "disable-on-404") == 0) {
5332 /* enable a graceful server shutdown on an HTTP 404 response */
5333 curproxy->options |= PR_O_DISABLE404;
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 Tarreau48494c02007-11-30 10:41:39 +01005336 }
Willy Tarreauef781042010-01-27 11:53:01 +01005337 else if (strcmp(args[1], "send-state") == 0) {
5338 /* enable emission of the apparent state of a server in HTTP checks */
5339 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005340 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5341 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005342 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005343 else if (strcmp(args[1], "expect") == 0) {
5344 const char *ptr_arg;
5345 int cur_arg;
5346
5347 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5348 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352
5353 cur_arg = 2;
5354 /* consider exclamation marks, sole or at the beginning of a word */
5355 while (*(ptr_arg = args[cur_arg])) {
5356 while (*ptr_arg == '!') {
5357 curproxy->options2 ^= PR_O2_EXP_INV;
5358 ptr_arg++;
5359 }
5360 if (*ptr_arg)
5361 break;
5362 cur_arg++;
5363 }
5364 /* now ptr_arg points to the beginning of a word past any possible
5365 * exclamation mark, and cur_arg is the argument which holds this word.
5366 */
5367 if (strcmp(ptr_arg, "status") == 0) {
5368 if (!*(args[cur_arg + 1])) {
5369 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5370 file, linenum, args[0], args[1], ptr_arg);
5371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
5373 }
5374 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005375 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005376 curproxy->expect_str = strdup(args[cur_arg + 1]);
5377 }
5378 else if (strcmp(ptr_arg, "string") == 0) {
5379 if (!*(args[cur_arg + 1])) {
5380 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5381 file, linenum, args[0], args[1], ptr_arg);
5382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
5385 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005386 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005387 curproxy->expect_str = strdup(args[cur_arg + 1]);
5388 }
5389 else if (strcmp(ptr_arg, "rstatus") == 0) {
5390 if (!*(args[cur_arg + 1])) {
5391 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5392 file, linenum, args[0], args[1], ptr_arg);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005397 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005398 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005399 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005400 free(curproxy->expect_regex);
5401 curproxy->expect_regex = NULL;
5402 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005403 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005404 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5405 error = NULL;
5406 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5407 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5408 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5409 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413 }
5414 else if (strcmp(ptr_arg, "rstring") == 0) {
5415 if (!*(args[cur_arg + 1])) {
5416 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5417 file, linenum, args[0], args[1], ptr_arg);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005422 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005423 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005424 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005425 free(curproxy->expect_regex);
5426 curproxy->expect_regex = NULL;
5427 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005428 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005429 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5430 error = NULL;
5431 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5432 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5433 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5434 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
5437 }
5438 }
5439 else {
5440 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5441 file, linenum, args[0], args[1], ptr_arg);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005446 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005447 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 +02005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005450 }
5451 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452 else if (!strcmp(args[0], "tcp-check")) {
5453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5454 err_code |= ERR_WARN;
5455
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005456 if (strcmp(args[1], "comment") == 0) {
5457 int cur_arg;
5458 struct tcpcheck_rule *tcpcheck;
5459
5460 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005461 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005462 tcpcheck->action = TCPCHK_ACT_COMMENT;
5463
5464 if (!*args[cur_arg + 1]) {
5465 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5466 file, linenum, args[cur_arg]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470
5471 tcpcheck->comment = strdup(args[cur_arg + 1]);
5472
5473 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005474 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5475 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005476 }
5477 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005478 const char *ptr_arg;
5479 int cur_arg;
5480 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005481
5482 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005483 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5484 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5485 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5486 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5487 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005488
Willy Tarreau5581c272015-05-13 12:24:53 +02005489 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5490 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5491 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5492 file, linenum);
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005495 }
5496
5497 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005498 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005499 tcpcheck->action = TCPCHK_ACT_CONNECT;
5500
5501 /* parsing each parameters to fill up the rule */
5502 while (*(ptr_arg = args[cur_arg])) {
5503 /* tcp port */
5504 if (strcmp(args[cur_arg], "port") == 0) {
5505 if ( (atol(args[cur_arg + 1]) > 65535) ||
5506 (atol(args[cur_arg + 1]) < 1) ){
5507 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5508 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
5511 }
5512 tcpcheck->port = atol(args[cur_arg + 1]);
5513 cur_arg += 2;
5514 }
5515 /* send proxy protocol */
5516 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5517 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5518 cur_arg++;
5519 }
5520#ifdef USE_OPENSSL
5521 else if (strcmp(args[cur_arg], "ssl") == 0) {
5522 curproxy->options |= PR_O_TCPCHK_SSL;
5523 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5524 cur_arg++;
5525 }
5526#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005527 /* comment for this tcpcheck line */
5528 else if (strcmp(args[cur_arg], "comment") == 0) {
5529 if (!*args[cur_arg + 1]) {
5530 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5531 file, linenum, args[cur_arg]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535 tcpcheck->comment = strdup(args[cur_arg + 1]);
5536 cur_arg += 2;
5537 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005538 else {
5539#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005540 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 +01005541#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005542 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 +01005543#endif /* USE_OPENSSL */
5544 file, linenum, args[0], args[1], args[cur_arg]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548
5549 }
5550
5551 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5552 }
5553 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005554 if (! *(args[2]) ) {
5555 /* SEND string expected */
5556 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5557 file, linenum, args[0], args[1], args[2]);
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
5560 } else {
5561 struct tcpcheck_rule *tcpcheck;
5562
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005563 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005564
5565 tcpcheck->action = TCPCHK_ACT_SEND;
5566 tcpcheck->string_len = strlen(args[2]);
5567 tcpcheck->string = strdup(args[2]);
5568 tcpcheck->expect_regex = NULL;
5569
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005570 /* comment for this tcpcheck line */
5571 if (strcmp(args[3], "comment") == 0) {
5572 if (!*args[4]) {
5573 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5574 file, linenum, args[3]);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
5578 tcpcheck->comment = strdup(args[4]);
5579 }
5580
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005581 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5582 }
5583 }
5584 else if (strcmp(args[1], "send-binary") == 0) {
5585 if (! *(args[2]) ) {
5586 /* SEND binary string expected */
5587 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5588 file, linenum, args[0], args[1], args[2]);
5589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
5591 } else {
5592 struct tcpcheck_rule *tcpcheck;
5593 char *err = NULL;
5594
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005595 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005596
5597 tcpcheck->action = TCPCHK_ACT_SEND;
5598 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5599 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5600 file, linenum, args[0], args[1], args[2], err);
5601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
5604 tcpcheck->expect_regex = NULL;
5605
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005606 /* comment for this tcpcheck line */
5607 if (strcmp(args[3], "comment") == 0) {
5608 if (!*args[4]) {
5609 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5610 file, linenum, args[3]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614 tcpcheck->comment = strdup(args[4]);
5615 }
5616
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005617 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5618 }
5619 }
5620 else if (strcmp(args[1], "expect") == 0) {
5621 const char *ptr_arg;
5622 int cur_arg;
5623 int inverse = 0;
5624
5625 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5626 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
5630
5631 cur_arg = 2;
5632 /* consider exclamation marks, sole or at the beginning of a word */
5633 while (*(ptr_arg = args[cur_arg])) {
5634 while (*ptr_arg == '!') {
5635 inverse = !inverse;
5636 ptr_arg++;
5637 }
5638 if (*ptr_arg)
5639 break;
5640 cur_arg++;
5641 }
5642 /* now ptr_arg points to the beginning of a word past any possible
5643 * exclamation mark, and cur_arg is the argument which holds this word.
5644 */
5645 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005646 struct tcpcheck_rule *tcpcheck;
5647 char *err = NULL;
5648
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649 if (!*(args[cur_arg + 1])) {
5650 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5651 file, linenum, args[0], args[1], ptr_arg);
5652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
5654 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005655
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005656 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005657
5658 tcpcheck->action = TCPCHK_ACT_EXPECT;
5659 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5660 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5661 file, linenum, args[0], args[1], args[2], err);
5662 err_code |= ERR_ALERT | ERR_FATAL;
5663 goto out;
5664 }
5665 tcpcheck->expect_regex = NULL;
5666 tcpcheck->inverse = inverse;
5667
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005668 /* tcpcheck comment */
5669 cur_arg += 2;
5670 if (strcmp(args[cur_arg], "comment") == 0) {
5671 if (!*args[cur_arg + 1]) {
5672 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5673 file, linenum, args[cur_arg + 1]);
5674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677 tcpcheck->comment = strdup(args[cur_arg + 1]);
5678 }
5679
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005680 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5681 }
5682 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005683 struct tcpcheck_rule *tcpcheck;
5684
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685 if (!*(args[cur_arg + 1])) {
5686 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5687 file, linenum, args[0], args[1], ptr_arg);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005691
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005692 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005693
5694 tcpcheck->action = TCPCHK_ACT_EXPECT;
5695 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5696 tcpcheck->string = strdup(args[cur_arg + 1]);
5697 tcpcheck->expect_regex = NULL;
5698 tcpcheck->inverse = inverse;
5699
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005700 /* tcpcheck comment */
5701 cur_arg += 2;
5702 if (strcmp(args[cur_arg], "comment") == 0) {
5703 if (!*args[cur_arg + 1]) {
5704 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5705 file, linenum, args[cur_arg + 1]);
5706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
5708 }
5709 tcpcheck->comment = strdup(args[cur_arg + 1]);
5710 }
5711
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005712 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5713 }
5714 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005715 struct tcpcheck_rule *tcpcheck;
5716
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005717 if (!*(args[cur_arg + 1])) {
5718 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5719 file, linenum, args[0], args[1], ptr_arg);
5720 err_code |= ERR_ALERT | ERR_FATAL;
5721 goto out;
5722 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005723
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005724 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005725
5726 tcpcheck->action = TCPCHK_ACT_EXPECT;
5727 tcpcheck->string_len = 0;
5728 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005729 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5730 error = NULL;
5731 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5732 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5733 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5734 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
5738 tcpcheck->inverse = inverse;
5739
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005740 /* tcpcheck comment */
5741 cur_arg += 2;
5742 if (strcmp(args[cur_arg], "comment") == 0) {
5743 if (!*args[cur_arg + 1]) {
5744 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5745 file, linenum, args[cur_arg + 1]);
5746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
5748 }
5749 tcpcheck->comment = strdup(args[cur_arg + 1]);
5750 }
5751
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005752 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5753 }
5754 else {
5755 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5756 file, linenum, args[0], args[1], ptr_arg);
5757 err_code |= ERR_ALERT | ERR_FATAL;
5758 goto out;
5759 }
5760 }
5761 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005762 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
5766 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005767 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005768 if (curproxy == &defproxy) {
5769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005772 }
5773
Willy Tarreaub80c2302007-11-30 20:51:32 +01005774 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005776
5777 if (strcmp(args[1], "fail") == 0) {
5778 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005779 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005780 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5781 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005784 }
5785
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005786 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5787 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5788 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005791 }
5792 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5793 }
5794 else {
5795 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005798 }
5799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800#ifdef TPROXY
5801 else if (!strcmp(args[0], "transparent")) {
5802 /* enable transparent proxy connections */
5803 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005804 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 }
5807#endif
5808 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005811
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 if (*(args[1]) == 0) {
5813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 }
5817 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005818 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005821 else if (!strcmp(args[0], "backlog")) { /* backlog */
5822 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005824
5825 if (*(args[1]) == 0) {
5826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005829 }
5830 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005831 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5832 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005833 }
Willy Tarreau86034312006-12-29 00:10:33 +01005834 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005837
Willy Tarreau86034312006-12-29 00:10:33 +01005838 if (*(args[1]) == 0) {
5839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005842 }
5843 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005844 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5845 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5848 if (*(args[1]) == 0) {
5849 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005853 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5854 if (err) {
5855 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5856 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005859 }
5860 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005861 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 }
5864 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005865 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005866 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005867 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005868
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 if (curproxy == &defproxy) {
5870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005871 err_code |= ERR_ALERT | ERR_FATAL;
5872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005874 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005876
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005877 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005878 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005879 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005880 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005881 goto out;
5882 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005883
5884 proto = protocol_by_family(sk->ss_family);
5885 if (!proto || !proto->connect) {
5886 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5887 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890 }
5891
5892 if (port1 != port2) {
5893 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5894 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005898
5899 if (!port1) {
5900 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5901 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
5904 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005905
William Lallemanddf1425a2015-04-28 20:17:49 +02005906 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5907 goto out;
5908
Willy Tarreaud5191e72010-02-09 20:50:45 +01005909 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005910 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 }
5912 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005913 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005915
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005916 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5917 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005922 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005923 /**
5924 * The syntax for hash-type config element is
5925 * hash-type {map-based|consistent} [[<algo>] avalanche]
5926 *
5927 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5928 */
5929 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005930
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5932 err_code |= ERR_WARN;
5933
5934 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005935 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5936 }
5937 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005938 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5939 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005940 else if (strcmp(args[1], "avalanche") == 0) {
5941 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]);
5942 err_code |= ERR_ALERT | ERR_FATAL;
5943 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005944 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005945 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005946 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005947 err_code |= ERR_ALERT | ERR_FATAL;
5948 goto out;
5949 }
Bhaskar98634f02013-10-29 23:30:51 -04005950
5951 /* set the hash function to use */
5952 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005953 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005954 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005955
5956 /* if consistent with no argument, then avalanche modifier is also applied */
5957 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5958 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005959 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005960 /* set the hash function */
5961 if (!strcmp(args[2], "sdbm")) {
5962 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5963 }
5964 else if (!strcmp(args[2], "djb2")) {
5965 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005966 }
5967 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005968 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005969 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005970 else if (!strcmp(args[2], "crc32")) {
5971 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5972 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005973 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005974 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 -05005975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
5977 }
5978
5979 /* set the hash modifier */
5980 if (!strcmp(args[3], "avalanche")) {
5981 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5982 }
5983 else if (*args[3]) {
5984 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5985 err_code |= ERR_ALERT | ERR_FATAL;
5986 goto out;
5987 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005988 }
William Lallemanda73203e2012-03-12 12:48:57 +01005989 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005990 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5991 if (*(args[1]) == 0) {
5992 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5997 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5998 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5999 err_code |= ERR_ALERT | ERR_FATAL;
6000 goto out;
6001 }
6002 }
William Lallemanda73203e2012-03-12 12:48:57 +01006003 else if (strcmp(args[0], "unique-id-format") == 0) {
6004 if (!*(args[1])) {
6005 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
William Lallemand3203ff42012-11-11 17:30:56 +01006009 if (*(args[2])) {
6010 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
6013 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006014 free(curproxy->conf.uniqueid_format_string);
6015 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006016
Willy Tarreau62a61232013-04-12 18:13:46 +02006017 free(curproxy->conf.uif_file);
6018 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6019 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006020 }
William Lallemanda73203e2012-03-12 12:48:57 +01006021
6022 else if (strcmp(args[0], "unique-id-header") == 0) {
6023 if (!*(args[1])) {
6024 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
6028 free(curproxy->header_unique_id);
6029 curproxy->header_unique_id = strdup(args[1]);
6030 }
6031
William Lallemand723b73a2012-02-08 16:37:49 +01006032 else if (strcmp(args[0], "log-format") == 0) {
6033 if (!*(args[1])) {
6034 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
William Lallemand3203ff42012-11-11 17:30:56 +01006038 if (*(args[2])) {
6039 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6040 err_code |= ERR_ALERT | ERR_FATAL;
6041 goto out;
6042 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006043
Willy Tarreau62a61232013-04-12 18:13:46 +02006044 if (curproxy->conf.logformat_string != default_http_log_format &&
6045 curproxy->conf.logformat_string != default_tcp_log_format &&
6046 curproxy->conf.logformat_string != clf_http_log_format)
6047 free(curproxy->conf.logformat_string);
6048 curproxy->conf.logformat_string = strdup(args[1]);
6049
6050 free(curproxy->conf.lfs_file);
6051 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6052 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006053
6054 /* get a chance to improve log-format error reporting by
6055 * reporting the correct line-number when possible.
6056 */
6057 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6058 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6059 file, linenum, curproxy->id);
6060 err_code |= ERR_WARN;
6061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006063 else if (!strcmp(args[0], "log-format-sd")) {
6064 if (!*(args[1])) {
6065 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068 }
6069 if (*(args[2])) {
6070 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
6073 }
6074
6075 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6076 free(curproxy->conf.logformat_sd_string);
6077 curproxy->conf.logformat_sd_string = strdup(args[1]);
6078
6079 free(curproxy->conf.lfsd_file);
6080 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6081 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6082
6083 /* get a chance to improve log-format-sd error reporting by
6084 * reporting the correct line-number when possible.
6085 */
6086 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6087 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6088 file, linenum, curproxy->id);
6089 err_code |= ERR_WARN;
6090 }
6091 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006092 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6093 if (*(args[1]) == 0) {
6094 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
6097 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006098 chunk_destroy(&curproxy->log_tag);
6099 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006100 }
William Lallemand0f99e342011-10-12 17:50:54 +02006101 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6102 /* delete previous herited or defined syslog servers */
6103 struct logsrv *back;
6104
6105 if (*(args[1]) != 0) {
6106 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
6109 }
6110
William Lallemand723b73a2012-02-08 16:37:49 +01006111 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6112 LIST_DEL(&tmplogsrv->list);
6113 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006114 }
6115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006117 struct logsrv *logsrv;
6118
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006120 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006121 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006122 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006123 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006124 LIST_INIT(&node->list);
6125 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 }
6128 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006129 struct sockaddr_storage *sk;
6130 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006131 int arg = 0;
6132 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006133
Vincent Bernat02779b62016-04-03 13:48:43 +02006134 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135
Willy Tarreau18324f52014-06-27 18:10:07 +02006136 /* just after the address, a length may be specified */
6137 if (strcmp(args[arg+2], "len") == 0) {
6138 len = atoi(args[arg+3]);
6139 if (len < 80 || len > 65535) {
6140 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6141 file, linenum, args[arg+3]);
6142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
6144 }
6145 logsrv->maxlen = len;
6146
6147 /* skip these two args */
6148 arg += 2;
6149 }
6150 else
6151 logsrv->maxlen = MAX_SYSLOG_LEN;
6152
6153 if (logsrv->maxlen > global.max_syslog_len) {
6154 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006155 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6156 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6157 logline = my_realloc2(logline, global.max_syslog_len + 1);
6158 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006159 }
6160
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
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006207 sk = str2sa_range(args[1], &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
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006259 sk = str2sa_range(args[1], &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
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006344 sk = str2sa_range(args[cur_arg + 1], &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)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006529 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6530 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)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006626 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6627 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;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007089 struct cfg_section *cs = NULL;
7090 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
Willy Tarreaubaaee002006-06-26 02:48:02 +02007389 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007390 if (cs)
7391 err_code |= cs->section_parser(file, linenum, args, kwm);
7392 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007393 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007394 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007395 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007396
7397 if (err_code & ERR_ABORT)
7398 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007399 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007400 free(cfg_scope);
7401 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007402 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007403 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007404 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007405 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007406}
7407
Willy Tarreau64ab6072014-09-16 12:17:36 +02007408/* This function propagates processes from frontend <from> to backend <to> so
7409 * that it is always guaranteed that a backend pointed to by a frontend is
7410 * bound to all of its processes. After that, if the target is a "listen"
7411 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007412 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007413 * checked first to ensure that <to> is already bound to all processes of
7414 * <from>, there is no risk of looping and we ensure to follow the shortest
7415 * path to the destination.
7416 *
7417 * It is possible to set <to> to NULL for the first call so that the function
7418 * takes care of visiting the initial frontend in <from>.
7419 *
7420 * It is important to note that the function relies on the fact that all names
7421 * have already been resolved.
7422 */
7423void propagate_processes(struct proxy *from, struct proxy *to)
7424{
7425 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007426
7427 if (to) {
7428 /* check whether we need to go down */
7429 if (from->bind_proc &&
7430 (from->bind_proc & to->bind_proc) == from->bind_proc)
7431 return;
7432
7433 if (!from->bind_proc && !to->bind_proc)
7434 return;
7435
7436 to->bind_proc = from->bind_proc ?
7437 (to->bind_proc | from->bind_proc) : 0;
7438
7439 /* now propagate down */
7440 from = to;
7441 }
7442
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007443 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007444 return;
7445
Willy Tarreauf6b70012014-12-18 14:00:43 +01007446 if (from->state == PR_STSTOPPED)
7447 return;
7448
Willy Tarreau64ab6072014-09-16 12:17:36 +02007449 /* default_backend */
7450 if (from->defbe.be)
7451 propagate_processes(from, from->defbe.be);
7452
7453 /* use_backend */
7454 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007455 if (rule->dynamic)
7456 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007457 to = rule->be.backend;
7458 propagate_processes(from, to);
7459 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007460}
7461
Willy Tarreaubb925012009-07-23 13:36:36 +02007462/*
7463 * Returns the error code, 0 if OK, or any combination of :
7464 * - ERR_ABORT: must abort ASAP
7465 * - ERR_FATAL: we can continue parsing but not start the service
7466 * - ERR_WARN: a warning has been emitted
7467 * - ERR_ALERT: an alert has been emitted
7468 * Only the two first ones can stop processing, the two others are just
7469 * indicators.
7470 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007471int check_config_validity()
7472{
7473 int cfgerr = 0;
7474 struct proxy *curproxy = NULL;
7475 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007476 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007477 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007478 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007479 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007480
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007481 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007482 /*
7483 * Now, check for the integrity of all that we have collected.
7484 */
7485
7486 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007487 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007488
Willy Tarreau193b8c62012-11-22 00:17:38 +01007489 if (!global.tune.max_http_hdr)
7490 global.tune.max_http_hdr = MAX_HTTP_HDR;
7491
7492 if (!global.tune.cookie_len)
7493 global.tune.cookie_len = CAPTURE_LEN;
7494
7495 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7496
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007497 /* Post initialisation of the users and groups lists. */
7498 err_code = userlist_postinit();
7499 if (err_code != ERR_NONE)
7500 goto out;
7501
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007502 /* first, we will invert the proxy list order */
7503 curproxy = NULL;
7504 while (proxy) {
7505 struct proxy *next;
7506
7507 next = proxy->next;
7508 proxy->next = curproxy;
7509 curproxy = proxy;
7510 if (!next)
7511 break;
7512 proxy = next;
7513 }
7514
Willy Tarreau419ead82014-09-16 13:41:21 +02007515 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007516 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007517 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007518 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007519 struct act_rule *trule;
7520 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007521 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007522 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007523 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007524
Willy Tarreau050536d2012-10-04 08:47:34 +02007525 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007526 /* proxy ID not set, use automatic numbering with first
7527 * spare entry starting with next_pxid.
7528 */
7529 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7530 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7531 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007532 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007533 next_pxid++;
7534
Willy Tarreau55ea7572007-06-17 19:56:27 +02007535
Willy Tarreaubaaee002006-06-26 02:48:02 +02007536 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007537 /* ensure we don't keep listeners uselessly bound */
7538 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007539 free((void *)curproxy->table.peers.name);
7540 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007541 continue;
7542 }
7543
Willy Tarreau102df612014-05-07 23:56:38 +02007544 /* Check multi-process mode compatibility for the current proxy */
7545
7546 if (curproxy->bind_proc) {
7547 /* an explicit bind-process was specified, let's check how many
7548 * processes remain.
7549 */
David Carliere6c39412015-07-02 07:00:17 +00007550 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007551
7552 curproxy->bind_proc &= nbits(global.nbproc);
7553 if (!curproxy->bind_proc && nbproc == 1) {
7554 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);
7555 curproxy->bind_proc = 1;
7556 }
7557 else if (!curproxy->bind_proc && nbproc > 1) {
7558 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);
7559 curproxy->bind_proc = 0;
7560 }
7561 }
7562
Willy Tarreau3d209582014-05-09 17:06:11 +02007563 /* check and reduce the bind-proc of each listener */
7564 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7565 unsigned long mask;
7566
7567 if (!bind_conf->bind_proc)
7568 continue;
7569
7570 mask = nbits(global.nbproc);
7571 if (curproxy->bind_proc)
7572 mask &= curproxy->bind_proc;
7573 /* mask cannot be null here thanks to the previous checks */
7574
David Carliere6c39412015-07-02 07:00:17 +00007575 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007576 bind_conf->bind_proc &= mask;
7577
7578 if (!bind_conf->bind_proc && nbproc == 1) {
7579 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",
7580 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7581 bind_conf->bind_proc = mask & ~(mask - 1);
7582 }
7583 else if (!bind_conf->bind_proc && nbproc > 1) {
7584 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",
7585 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7586 bind_conf->bind_proc = 0;
7587 }
7588 }
7589
Willy Tarreauff01a212009-03-15 13:46:16 +01007590 switch (curproxy->mode) {
7591 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007592 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007593 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007594 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7595 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007596 cfgerr++;
7597 }
7598
7599 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007600 Warning("config : servers will be ignored for %s '%s'.\n",
7601 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007602 break;
7603
7604 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007605 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007606 break;
7607
7608 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007609 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007610 break;
7611 }
7612
Willy Tarreauf3934b82015-08-11 11:36:45 +02007613 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7614 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7615 proxy_type_str(curproxy), curproxy->id);
7616 err_code |= ERR_WARN;
7617 }
7618
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007619 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007620 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007621 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007622 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007624 cfgerr++;
7625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007626#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007627 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007628 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007630 cfgerr++;
7631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007632#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007633 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007634 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7635 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007636 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007637 }
7638 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007639 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007640 /* If no LB algo is set in a backend, and we're not in
7641 * transparent mode, dispatch mode nor proxy mode, we
7642 * want to use balance roundrobin by default.
7643 */
7644 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7645 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007646 }
7647 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007648
Willy Tarreau1620ec32011-08-06 17:05:02 +02007649 if (curproxy->options & PR_O_DISPATCH)
7650 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7651 else if (curproxy->options & PR_O_HTTP_PROXY)
7652 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7653 else if (curproxy->options & PR_O_TRANSP)
7654 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007655
Willy Tarreau1620ec32011-08-06 17:05:02 +02007656 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7657 if (curproxy->options & PR_O_DISABLE404) {
7658 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7659 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7660 err_code |= ERR_WARN;
7661 curproxy->options &= ~PR_O_DISABLE404;
7662 }
7663 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7664 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7665 "send-state", proxy_type_str(curproxy), curproxy->id);
7666 err_code |= ERR_WARN;
7667 curproxy->options &= ~PR_O2_CHK_SNDST;
7668 }
Willy Tarreauef781042010-01-27 11:53:01 +01007669 }
7670
Simon Horman98637e52014-06-20 12:30:16 +09007671 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7672 if (!global.external_check) {
7673 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7674 curproxy->id, "option external-check");
7675 cfgerr++;
7676 }
7677 if (!curproxy->check_command) {
7678 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7679 curproxy->id, "option external-check");
7680 cfgerr++;
7681 }
7682 }
7683
Simon Horman64e34162015-02-06 11:11:57 +09007684 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007685 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7686 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007687 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7688 "'email-alert myhostname', or 'email-alert to' "
7689 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007690 "to be present).\n",
7691 proxy_type_str(curproxy), curproxy->id);
7692 err_code |= ERR_WARN;
7693 free_email_alert(curproxy);
7694 }
7695 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007696 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007697 }
7698
Simon Horman98637e52014-06-20 12:30:16 +09007699 if (curproxy->check_command) {
7700 int clear = 0;
7701 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7702 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7703 "external-check command", proxy_type_str(curproxy), curproxy->id);
7704 err_code |= ERR_WARN;
7705 clear = 1;
7706 }
7707 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007708 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007709 curproxy->id, "external-check command");
7710 cfgerr++;
7711 }
7712 if (clear) {
7713 free(curproxy->check_command);
7714 curproxy->check_command = NULL;
7715 }
7716 }
7717
7718 if (curproxy->check_path) {
7719 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7720 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7721 "external-check path", proxy_type_str(curproxy), curproxy->id);
7722 err_code |= ERR_WARN;
7723 free(curproxy->check_path);
7724 curproxy->check_path = NULL;
7725 }
7726 }
7727
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007728 /* if a default backend was specified, let's find it */
7729 if (curproxy->defbe.name) {
7730 struct proxy *target;
7731
Willy Tarreauafb39922015-05-26 12:04:09 +02007732 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007733 if (!target) {
7734 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7735 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007736 cfgerr++;
7737 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007738 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7739 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007740 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007741 } else if (target->mode != curproxy->mode &&
7742 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7743
7744 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7745 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7746 curproxy->conf.file, curproxy->conf.line,
7747 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7748 target->conf.file, target->conf.line);
7749 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007750 } else {
7751 free(curproxy->defbe.name);
7752 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007753
7754 /* Emit a warning if this proxy also has some servers */
7755 if (curproxy->srv) {
7756 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7757 curproxy->id);
7758 err_code |= ERR_WARN;
7759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007760 }
7761 }
7762
Willy Tarreau55ea7572007-06-17 19:56:27 +02007763 /* find the target proxy for 'use_backend' rules */
7764 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007765 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007766 struct logformat_node *node;
7767 char *pxname;
7768
7769 /* Try to parse the string as a log format expression. If the result
7770 * of the parsing is only one entry containing a simple string, then
7771 * it's a standard string corresponding to a static rule, thus the
7772 * parsing is cancelled and be.name is restored to be resolved.
7773 */
7774 pxname = rule->be.name;
7775 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007776 curproxy->conf.args.ctx = ARGC_UBK;
7777 curproxy->conf.args.file = rule->file;
7778 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007779 err = NULL;
7780 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7781 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7782 rule->file, rule->line, pxname, err);
7783 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007784 cfgerr++;
7785 continue;
7786 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007787 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7788
7789 if (!LIST_ISEMPTY(&rule->be.expr)) {
7790 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7791 rule->dynamic = 1;
7792 free(pxname);
7793 continue;
7794 }
7795 /* simple string: free the expression and fall back to static rule */
7796 free(node->arg);
7797 free(node);
7798 }
7799
7800 rule->dynamic = 0;
7801 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007802
Willy Tarreauafb39922015-05-26 12:04:09 +02007803 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007804 if (!target) {
7805 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7806 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007807 cfgerr++;
7808 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007809 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7810 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007811 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007812 } else if (target->mode != curproxy->mode &&
7813 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7814
7815 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7816 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7817 curproxy->conf.file, curproxy->conf.line,
7818 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7819 target->conf.file, target->conf.line);
7820 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007821 } else {
7822 free((void *)rule->be.name);
7823 rule->be.backend = target;
7824 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007825 }
7826
Willy Tarreau64ab6072014-09-16 12:17:36 +02007827 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007828 list_for_each_entry(srule, &curproxy->server_rules, list) {
7829 struct server *target = findserver(curproxy, srule->srv.name);
7830
7831 if (!target) {
7832 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7833 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7834 cfgerr++;
7835 continue;
7836 }
7837 free((void *)srule->srv.name);
7838 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007839 }
7840
Emeric Brunb982a3d2010-01-04 15:45:53 +01007841 /* find the target table for 'stick' rules */
7842 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7843 struct proxy *target;
7844
Emeric Brun1d33b292010-01-04 15:47:17 +01007845 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7846 if (mrule->flags & STK_IS_STORE)
7847 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7848
Emeric Brunb982a3d2010-01-04 15:45:53 +01007849 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007850 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007851 else
7852 target = curproxy;
7853
7854 if (!target) {
7855 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7856 curproxy->id, mrule->table.name);
7857 cfgerr++;
7858 }
7859 else if (target->table.size == 0) {
7860 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7861 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7862 cfgerr++;
7863 }
Willy Tarreau12785782012-04-27 21:37:17 +02007864 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7865 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007866 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7867 cfgerr++;
7868 }
7869 else {
7870 free((void *)mrule->table.name);
7871 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007872 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007873 }
7874 }
7875
7876 /* find the target table for 'store response' rules */
7877 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7878 struct proxy *target;
7879
Emeric Brun1d33b292010-01-04 15:47:17 +01007880 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7881
Emeric Brunb982a3d2010-01-04 15:45:53 +01007882 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007883 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007884 else
7885 target = curproxy;
7886
7887 if (!target) {
7888 Alert("Proxy '%s': unable to find store table '%s'.\n",
7889 curproxy->id, mrule->table.name);
7890 cfgerr++;
7891 }
7892 else if (target->table.size == 0) {
7893 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7894 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7895 cfgerr++;
7896 }
Willy Tarreau12785782012-04-27 21:37:17 +02007897 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7898 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007899 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7900 cfgerr++;
7901 }
7902 else {
7903 free((void *)mrule->table.name);
7904 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007905 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007906 }
7907 }
7908
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007909 /* find the target table for 'tcp-request' layer 4 rules */
7910 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7911 struct proxy *target;
7912
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007913 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007914 continue;
7915
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007916 if (trule->arg.trk_ctr.table.n)
7917 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007918 else
7919 target = curproxy;
7920
7921 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007922 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007923 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007924 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007925 cfgerr++;
7926 }
7927 else if (target->table.size == 0) {
7928 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007929 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007930 cfgerr++;
7931 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007932 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007933 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007934 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007935 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007936 cfgerr++;
7937 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007938 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007939 free(trule->arg.trk_ctr.table.n);
7940 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007941 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007942 * to pass a list of counters to track and allocate them right here using
7943 * stktable_alloc_data_type().
7944 */
7945 }
7946 }
7947
Willy Tarreau620408f2016-10-21 16:37:51 +02007948 /* find the target table for 'tcp-request' layer 5 rules */
7949 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7950 struct proxy *target;
7951
7952 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7953 continue;
7954
7955 if (trule->arg.trk_ctr.table.n)
7956 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7957 else
7958 target = curproxy;
7959
7960 if (!target) {
7961 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7962 curproxy->id, trule->arg.trk_ctr.table.n,
7963 tcp_trk_idx(trule->action));
7964 cfgerr++;
7965 }
7966 else if (target->table.size == 0) {
7967 Alert("Proxy '%s': table '%s' used but not configured.\n",
7968 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7969 cfgerr++;
7970 }
7971 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7972 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7973 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7974 tcp_trk_idx(trule->action));
7975 cfgerr++;
7976 }
7977 else {
7978 free(trule->arg.trk_ctr.table.n);
7979 trule->arg.trk_ctr.table.t = &target->table;
7980 /* Note: if we decide to enhance the track-sc syntax, we may be able
7981 * to pass a list of counters to track and allocate them right here using
7982 * stktable_alloc_data_type().
7983 */
7984 }
7985 }
7986
Willy Tarreaud1f96522010-08-03 19:34:32 +02007987 /* find the target table for 'tcp-request' layer 6 rules */
7988 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7989 struct proxy *target;
7990
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007991 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007992 continue;
7993
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007994 if (trule->arg.trk_ctr.table.n)
7995 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007996 else
7997 target = curproxy;
7998
7999 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02008000 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008001 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008002 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02008003 cfgerr++;
8004 }
8005 else if (target->table.size == 0) {
8006 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008007 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008008 cfgerr++;
8009 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008010 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01008011 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008012 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008013 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01008014 cfgerr++;
8015 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008016 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008017 free(trule->arg.trk_ctr.table.n);
8018 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02008019 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02008020 * to pass a list of counters to track and allocate them right here using
8021 * stktable_alloc_data_type().
8022 */
8023 }
8024 }
8025
Baptiste Assmanne9544932015-11-03 23:31:35 +01008026 /* parse http-request capture rules to ensure id really exists */
8027 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8028 if (hrqrule->action != ACT_CUSTOM ||
8029 hrqrule->action_ptr != http_action_req_capture_by_id)
8030 continue;
8031
8032 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8033 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8034 curproxy->id, hrqrule->arg.capid.idx);
8035 cfgerr++;
8036 }
8037 }
8038
8039 /* parse http-response capture rules to ensure id really exists */
8040 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8041 if (hrqrule->action != ACT_CUSTOM ||
8042 hrqrule->action_ptr != http_action_res_capture_by_id)
8043 continue;
8044
8045 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8046 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8047 curproxy->id, hrqrule->arg.capid.idx);
8048 cfgerr++;
8049 }
8050 }
8051
Willy Tarreau09448f72014-06-25 18:12:15 +02008052 /* find the target table for 'http-request' layer 7 rules */
8053 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8054 struct proxy *target;
8055
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008056 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008057 continue;
8058
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008059 if (hrqrule->arg.trk_ctr.table.n)
8060 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008061 else
8062 target = curproxy;
8063
8064 if (!target) {
8065 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008066 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008067 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008068 cfgerr++;
8069 }
8070 else if (target->table.size == 0) {
8071 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008072 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008073 cfgerr++;
8074 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008075 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008076 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008077 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008078 http_trk_idx(hrqrule->action));
8079 cfgerr++;
8080 }
8081 else {
8082 free(hrqrule->arg.trk_ctr.table.n);
8083 hrqrule->arg.trk_ctr.table.t = &target->table;
8084 /* Note: if we decide to enhance the track-sc syntax, we may be able
8085 * to pass a list of counters to track and allocate them right here using
8086 * stktable_alloc_data_type().
8087 */
8088 }
8089 }
8090
8091 /* find the target table for 'http-response' layer 7 rules */
8092 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8093 struct proxy *target;
8094
8095 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8096 continue;
8097
8098 if (hrqrule->arg.trk_ctr.table.n)
8099 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8100 else
8101 target = curproxy;
8102
8103 if (!target) {
8104 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8105 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8106 http_trk_idx(hrqrule->action));
8107 cfgerr++;
8108 }
8109 else if (target->table.size == 0) {
8110 Alert("Proxy '%s': table '%s' used but not configured.\n",
8111 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8112 cfgerr++;
8113 }
8114 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8115 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8116 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8117 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008118 cfgerr++;
8119 }
8120 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008121 free(hrqrule->arg.trk_ctr.table.n);
8122 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008123 /* Note: if we decide to enhance the track-sc syntax, we may be able
8124 * to pass a list of counters to track and allocate them right here using
8125 * stktable_alloc_data_type().
8126 */
8127 }
8128 }
8129
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008130 /* move any "block" rules at the beginning of the http-request rules */
8131 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8132 /* insert block_rules into http_req_rules at the beginning */
8133 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8134 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8135 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8136 curproxy->http_req_rules.n = curproxy->block_rules.n;
8137 LIST_INIT(&curproxy->block_rules);
8138 }
8139
Emeric Brun32da3c42010-09-23 18:39:19 +02008140 if (curproxy->table.peers.name) {
8141 struct peers *curpeers = peers;
8142
8143 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8144 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8145 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008146 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008147 break;
8148 }
8149 }
8150
8151 if (!curpeers) {
8152 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8153 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008154 free((void *)curproxy->table.peers.name);
8155 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008156 cfgerr++;
8157 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008158 else if (curpeers->state == PR_STSTOPPED) {
8159 /* silently disable this peers section */
8160 curproxy->table.peers.p = NULL;
8161 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008162 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008163 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8164 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008165 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008166 cfgerr++;
8167 }
8168 }
8169
Simon Horman9dc49962015-01-30 11:22:59 +09008170
8171 if (curproxy->email_alert.mailers.name) {
8172 struct mailers *curmailers = mailers;
8173
8174 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8175 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8176 free(curproxy->email_alert.mailers.name);
8177 curproxy->email_alert.mailers.m = curmailers;
8178 curmailers->users++;
8179 break;
8180 }
8181 }
8182
8183 if (!curmailers) {
8184 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8185 curproxy->id, curproxy->email_alert.mailers.name);
8186 free_email_alert(curproxy);
8187 cfgerr++;
8188 }
8189 }
8190
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008191 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008192 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008193 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8194 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8195 "proxy", curproxy->id);
8196 cfgerr++;
8197 goto out_uri_auth_compat;
8198 }
8199
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008200 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008201 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008202 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008203 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008204
Willy Tarreau95fa4692010-02-01 13:05:50 +01008205 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8206 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008207
8208 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008209 uri_auth_compat_req[i++] = "realm";
8210 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8211 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008212
Willy Tarreau95fa4692010-02-01 13:05:50 +01008213 uri_auth_compat_req[i++] = "unless";
8214 uri_auth_compat_req[i++] = "{";
8215 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8216 uri_auth_compat_req[i++] = "}";
8217 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008218
Willy Tarreauff011f22011-01-06 17:51:27 +01008219 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8220 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008221 cfgerr++;
8222 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008223 }
8224
Willy Tarreauff011f22011-01-06 17:51:27 +01008225 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008226
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008227 if (curproxy->uri_auth->auth_realm) {
8228 free(curproxy->uri_auth->auth_realm);
8229 curproxy->uri_auth->auth_realm = NULL;
8230 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008231
8232 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008233 }
8234out_uri_auth_compat:
8235
Dragan Dosen43885c72015-10-01 13:18:13 +02008236 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008237 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008238 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8239 if (!curproxy->conf.logformat_sd_string) {
8240 /* set the default logformat_sd_string */
8241 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8242 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008243 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008244 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008245 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008246
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008247 /* compile the log format */
8248 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008249 if (curproxy->conf.logformat_string != default_http_log_format &&
8250 curproxy->conf.logformat_string != default_tcp_log_format &&
8251 curproxy->conf.logformat_string != clf_http_log_format)
8252 free(curproxy->conf.logformat_string);
8253 curproxy->conf.logformat_string = NULL;
8254 free(curproxy->conf.lfs_file);
8255 curproxy->conf.lfs_file = NULL;
8256 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008257
8258 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8259 free(curproxy->conf.logformat_sd_string);
8260 curproxy->conf.logformat_sd_string = NULL;
8261 free(curproxy->conf.lfsd_file);
8262 curproxy->conf.lfsd_file = NULL;
8263 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008264 }
8265
Willy Tarreau62a61232013-04-12 18:13:46 +02008266 if (curproxy->conf.logformat_string) {
8267 curproxy->conf.args.ctx = ARGC_LOG;
8268 curproxy->conf.args.file = curproxy->conf.lfs_file;
8269 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008270 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008271 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008272 SMP_VAL_FE_LOG_END, &err)) {
8273 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8274 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8275 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008276 cfgerr++;
8277 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008278 curproxy->conf.args.file = NULL;
8279 curproxy->conf.args.line = 0;
8280 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008281
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008282 if (curproxy->conf.logformat_sd_string) {
8283 curproxy->conf.args.ctx = ARGC_LOGSD;
8284 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8285 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008286 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008287 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 +01008288 SMP_VAL_FE_LOG_END, &err)) {
8289 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8290 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8291 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008292 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008293 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8294 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8295 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8296 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008297 cfgerr++;
8298 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008299 curproxy->conf.args.file = NULL;
8300 curproxy->conf.args.line = 0;
8301 }
8302
Willy Tarreau62a61232013-04-12 18:13:46 +02008303 if (curproxy->conf.uniqueid_format_string) {
8304 curproxy->conf.args.ctx = ARGC_UIF;
8305 curproxy->conf.args.file = curproxy->conf.uif_file;
8306 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008307 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008308 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 +01008309 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8310 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8311 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8312 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008313 cfgerr++;
8314 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008315 curproxy->conf.args.file = NULL;
8316 curproxy->conf.args.line = 0;
8317 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008318
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008319 /* only now we can check if some args remain unresolved.
8320 * This must be done after the users and groups resolution.
8321 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008322 cfgerr += smp_resolve_args(curproxy);
8323 if (!cfgerr)
8324 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008325
Willy Tarreau2738a142006-07-08 17:28:09 +02008326 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008327 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008328 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008329 (!curproxy->timeout.connect ||
8330 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008331 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008332 " | While not properly invalid, you will certainly encounter various problems\n"
8333 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008334 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008335 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008336 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008337 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008338
Willy Tarreau1fa31262007-12-03 00:36:16 +01008339 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8340 * We must still support older configurations, so let's find out whether those
8341 * parameters have been set or must be copied from contimeouts.
8342 */
8343 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008344 if (!curproxy->timeout.tarpit ||
8345 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008346 /* tarpit timeout not set. We search in the following order:
8347 * default.tarpit, curr.connect, default.connect.
8348 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008349 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008350 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008351 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008352 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008353 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008354 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008355 }
8356 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008357 (!curproxy->timeout.queue ||
8358 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008359 /* queue timeout not set. We search in the following order:
8360 * default.queue, curr.connect, default.connect.
8361 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008362 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008363 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008364 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008365 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008366 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008367 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008368 }
8369 }
8370
Willy Tarreau1620ec32011-08-06 17:05:02 +02008371 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008372 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008373 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008374 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008375 }
8376
Willy Tarreau215663d2014-06-13 18:30:23 +02008377 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8378 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8379 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8380 proxy_type_str(curproxy), curproxy->id);
8381 err_code |= ERR_WARN;
8382 }
8383
Willy Tarreau193b8c62012-11-22 00:17:38 +01008384 /* ensure that cookie capture length is not too large */
8385 if (curproxy->capture_len >= global.tune.cookie_len) {
8386 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8387 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8388 err_code |= ERR_WARN;
8389 curproxy->capture_len = global.tune.cookie_len - 1;
8390 }
8391
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008392 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008393 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008394 curproxy->req_cap_pool = create_pool("ptrcap",
8395 curproxy->nb_req_cap * sizeof(char *),
8396 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008397 }
8398
8399 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008400 curproxy->rsp_cap_pool = create_pool("ptrcap",
8401 curproxy->nb_rsp_cap * sizeof(char *),
8402 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008403 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008404
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008405 switch (curproxy->load_server_state_from_file) {
8406 case PR_SRV_STATE_FILE_UNSPEC:
8407 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8408 break;
8409 case PR_SRV_STATE_FILE_GLOBAL:
8410 if (!global.server_state_file) {
8411 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",
8412 curproxy->id);
8413 err_code |= ERR_WARN;
8414 }
8415 break;
8416 }
8417
Willy Tarreaubaaee002006-06-26 02:48:02 +02008418 /* first, we will invert the servers list order */
8419 newsrv = NULL;
8420 while (curproxy->srv) {
8421 struct server *next;
8422
8423 next = curproxy->srv->next;
8424 curproxy->srv->next = newsrv;
8425 newsrv = curproxy->srv;
8426 if (!next)
8427 break;
8428 curproxy->srv = next;
8429 }
8430
Willy Tarreau17edc812014-01-03 12:14:34 +01008431 /* Check that no server name conflicts. This causes trouble in the stats.
8432 * We only emit a warning for the first conflict affecting each server,
8433 * in order to avoid combinatory explosion if all servers have the same
8434 * name. We do that only for servers which do not have an explicit ID,
8435 * because these IDs were made also for distinguishing them and we don't
8436 * want to annoy people who correctly manage them.
8437 */
8438 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8439 struct server *other_srv;
8440
8441 if (newsrv->puid)
8442 continue;
8443
8444 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8445 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8446 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8447 newsrv->conf.file, newsrv->conf.line,
8448 proxy_type_str(curproxy), curproxy->id,
8449 newsrv->id, other_srv->conf.line);
8450 break;
8451 }
8452 }
8453 }
8454
Willy Tarreaudd701652010-05-25 23:03:02 +02008455 /* assign automatic UIDs to servers which don't have one yet */
8456 next_id = 1;
8457 newsrv = curproxy->srv;
8458 while (newsrv != NULL) {
8459 if (!newsrv->puid) {
8460 /* server ID not set, use automatic numbering with first
8461 * spare entry starting with next_svid.
8462 */
8463 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8464 newsrv->conf.id.key = newsrv->puid = next_id;
8465 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8466 }
8467 next_id++;
8468 newsrv = newsrv->next;
8469 }
8470
Willy Tarreau20697042007-11-15 23:26:18 +01008471 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008472 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008473
Willy Tarreau62c3be22012-01-20 13:12:32 +01008474 /*
8475 * If this server supports a maxconn parameter, it needs a dedicated
8476 * tasks to fill the emptied slots when a connection leaves.
8477 * Also, resolve deferred tracking dependency if needed.
8478 */
8479 newsrv = curproxy->srv;
8480 while (newsrv != NULL) {
8481 if (newsrv->minconn > newsrv->maxconn) {
8482 /* Only 'minconn' was specified, or it was higher than or equal
8483 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8484 * this will avoid further useless expensive computations.
8485 */
8486 newsrv->maxconn = newsrv->minconn;
8487 } else if (newsrv->maxconn && !newsrv->minconn) {
8488 /* minconn was not specified, so we set it to maxconn */
8489 newsrv->minconn = newsrv->maxconn;
8490 }
8491
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008492#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008493 if (newsrv->use_ssl || newsrv->check.use_ssl)
8494 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008495#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008496
Willy Tarreau2f075e92013-12-03 11:11:34 +01008497 /* set the check type on the server */
8498 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8499
Willy Tarreau62c3be22012-01-20 13:12:32 +01008500 if (newsrv->trackit) {
8501 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008502 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008503 char *pname, *sname;
8504
8505 pname = newsrv->trackit;
8506 sname = strrchr(pname, '/');
8507
8508 if (sname)
8509 *sname++ = '\0';
8510 else {
8511 sname = pname;
8512 pname = NULL;
8513 }
8514
8515 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008516 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008517 if (!px) {
8518 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8519 proxy_type_str(curproxy), curproxy->id,
8520 newsrv->id, pname);
8521 cfgerr++;
8522 goto next_srv;
8523 }
8524 } else
8525 px = curproxy;
8526
8527 srv = findserver(px, sname);
8528 if (!srv) {
8529 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8530 proxy_type_str(curproxy), curproxy->id,
8531 newsrv->id, sname);
8532 cfgerr++;
8533 goto next_srv;
8534 }
8535
Willy Tarreau32091232014-05-16 13:52:00 +02008536 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8537 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8538 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008539 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008540 "tracking as it does not have any check nor agent enabled.\n",
8541 proxy_type_str(curproxy), curproxy->id,
8542 newsrv->id, px->id, srv->id);
8543 cfgerr++;
8544 goto next_srv;
8545 }
8546
8547 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8548
8549 if (loop) {
8550 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8551 "belongs to a tracking chain looping back to %s/%s.\n",
8552 proxy_type_str(curproxy), curproxy->id,
8553 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008554 cfgerr++;
8555 goto next_srv;
8556 }
8557
8558 if (curproxy != px &&
8559 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8560 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8561 "tracking: disable-on-404 option inconsistency.\n",
8562 proxy_type_str(curproxy), curproxy->id,
8563 newsrv->id, px->id, srv->id);
8564 cfgerr++;
8565 goto next_srv;
8566 }
8567
Willy Tarreau62c3be22012-01-20 13:12:32 +01008568 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008569 newsrv->tracknext = srv->trackers;
8570 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008571
8572 free(newsrv->trackit);
8573 newsrv->trackit = NULL;
8574 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008575
8576 /*
8577 * resolve server's resolvers name and update the resolvers pointer
8578 * accordingly
8579 */
8580 if (newsrv->resolvers_id) {
8581 struct dns_resolvers *curr_resolvers;
8582 int found;
8583
8584 found = 0;
8585 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8586 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8587 found = 1;
8588 break;
8589 }
8590 }
8591
8592 if (!found) {
8593 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8594 proxy_type_str(curproxy), curproxy->id,
8595 newsrv->id, newsrv->resolvers_id);
8596 cfgerr++;
8597 } else {
8598 free(newsrv->resolvers_id);
8599 newsrv->resolvers_id = NULL;
8600 if (newsrv->resolution)
8601 newsrv->resolution->resolvers = curr_resolvers;
8602 }
8603 }
8604 else {
8605 /* if no resolvers section associated to this server
8606 * we can clean up the associated resolution structure
8607 */
8608 if (newsrv->resolution) {
8609 free(newsrv->resolution->hostname_dn);
8610 newsrv->resolution->hostname_dn = NULL;
8611 free(newsrv->resolution);
8612 newsrv->resolution = NULL;
8613 }
8614 }
8615
Willy Tarreau62c3be22012-01-20 13:12:32 +01008616 next_srv:
8617 newsrv = newsrv->next;
8618 }
8619
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008620 /* We have to initialize the server lookup mechanism depending
8621 * on what LB algorithm was choosen.
8622 */
8623
8624 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8625 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8626 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008627 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8628 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8629 init_server_map(curproxy);
8630 } else {
8631 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8632 fwrr_init_server_groups(curproxy);
8633 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008634 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008635
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008636 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008637 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8638 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8639 fwlc_init_server_tree(curproxy);
8640 } else {
8641 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8642 fas_init_server_tree(curproxy);
8643 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008644 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008645
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008646 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008647 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8648 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8649 chash_init_server_tree(curproxy);
8650 } else {
8651 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8652 init_server_map(curproxy);
8653 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008654 break;
8655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008656
8657 if (curproxy->options & PR_O_LOGASAP)
8658 curproxy->to_log &= ~LW_BYTES;
8659
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008660 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008661 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8662 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008663 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8664 proxy_type_str(curproxy), curproxy->id);
8665 err_code |= ERR_WARN;
8666 }
8667
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008668 if (curproxy->mode != PR_MODE_HTTP) {
8669 int optnum;
8670
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008671 if (curproxy->uri_auth) {
8672 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8673 proxy_type_str(curproxy), curproxy->id);
8674 err_code |= ERR_WARN;
8675 curproxy->uri_auth = NULL;
8676 }
8677
Willy Tarreau87cf5142011-08-19 22:57:24 +02008678 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008679 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8680 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8681 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008682 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008683 }
8684
8685 if (curproxy->options & PR_O_ORGTO) {
8686 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8687 "originalto", proxy_type_str(curproxy), curproxy->id);
8688 err_code |= ERR_WARN;
8689 curproxy->options &= ~PR_O_ORGTO;
8690 }
8691
8692 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8693 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8694 (curproxy->cap & cfg_opts[optnum].cap) &&
8695 (curproxy->options & cfg_opts[optnum].val)) {
8696 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8697 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8698 err_code |= ERR_WARN;
8699 curproxy->options &= ~cfg_opts[optnum].val;
8700 }
8701 }
8702
8703 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8704 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8705 (curproxy->cap & cfg_opts2[optnum].cap) &&
8706 (curproxy->options2 & cfg_opts2[optnum].val)) {
8707 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8708 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8709 err_code |= ERR_WARN;
8710 curproxy->options2 &= ~cfg_opts2[optnum].val;
8711 }
8712 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008713
Willy Tarreau29fbe512015-08-20 19:35:14 +02008714#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008715 if (curproxy->conn_src.bind_hdr_occ) {
8716 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008717 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008718 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008719 err_code |= ERR_WARN;
8720 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008721#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008722 }
8723
Willy Tarreaubaaee002006-06-26 02:48:02 +02008724 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008725 * ensure that we're not cross-dressing a TCP server into HTTP.
8726 */
8727 newsrv = curproxy->srv;
8728 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008729 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008730 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8731 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008732 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008733 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008734
Willy Tarreau0cec3312011-10-31 13:49:26 +01008735 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8736 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8737 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8738 err_code |= ERR_WARN;
8739 }
8740
Willy Tarreauc93cd162014-05-13 15:54:22 +02008741 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008742 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8743 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8744 err_code |= ERR_WARN;
8745 }
8746
Willy Tarreau29fbe512015-08-20 19:35:14 +02008747#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008748 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8749 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008750 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 +01008751 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008752 err_code |= ERR_WARN;
8753 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008754#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008755 newsrv = newsrv->next;
8756 }
8757
Willy Tarreaue42bd962014-09-16 16:21:19 +02008758 /* check if we have a frontend with "tcp-request content" looking at L7
8759 * with no inspect-delay
8760 */
8761 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8762 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008763 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008764 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008765 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008766 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008767 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008768 break;
8769 }
8770
8771 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8772 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8773 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8774 " This means that these rules will randomly find their contents. This can be fixed by"
8775 " setting the tcp-request inspect-delay.\n",
8776 proxy_type_str(curproxy), curproxy->id);
8777 err_code |= ERR_WARN;
8778 }
8779 }
8780
Christopher Fauletd7c91962015-04-30 11:48:27 +02008781 /* Check filter configuration, if any */
8782 cfgerr += flt_check(curproxy);
8783
Willy Tarreauc1a21672009-08-16 22:37:44 +02008784 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008785 if (!curproxy->accept)
8786 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008787
Willy Tarreauc1a21672009-08-16 22:37:44 +02008788 if (curproxy->tcp_req.inspect_delay ||
8789 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008790 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008791
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008792 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008793 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008794 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008795 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008796
8797 /* both TCP and HTTP must check switching rules */
8798 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008799
8800 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008801 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008802 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8803 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008804 if (curproxy->mode == PR_MODE_HTTP) {
8805 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8806 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8807 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008808 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008809 }
8810
8811 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008812 if (curproxy->tcp_req.inspect_delay ||
8813 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8814 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8815
Emeric Brun97679e72010-09-23 17:56:44 +02008816 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8817 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8818
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008819 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008820 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008821 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008822 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008823
8824 /* If the backend does requires RDP cookie persistence, we have to
8825 * enable the corresponding analyser.
8826 */
8827 if (curproxy->options2 & PR_O2_RDPC_PRST)
8828 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008829
8830 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008831 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008832 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8833 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008834 if (curproxy->mode == PR_MODE_HTTP) {
8835 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8836 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8837 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008838 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008839 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008840 }
8841
8842 /***********************************************************/
8843 /* At this point, target names have already been resolved. */
8844 /***********************************************************/
8845
8846 /* Check multi-process mode compatibility */
8847
8848 if (global.nbproc > 1 && global.stats_fe) {
8849 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8850 unsigned long mask;
8851
8852 mask = nbits(global.nbproc);
8853 if (global.stats_fe->bind_proc)
8854 mask &= global.stats_fe->bind_proc;
8855
8856 if (bind_conf->bind_proc)
8857 mask &= bind_conf->bind_proc;
8858
8859 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008860 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008861 break;
8862 }
8863 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8864 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");
8865 }
8866 }
8867
8868 /* Make each frontend inherit bind-process from its listeners when not specified. */
8869 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8870 if (curproxy->bind_proc)
8871 continue;
8872
8873 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8874 unsigned long mask;
8875
Willy Tarreaue428b082015-05-04 21:57:58 +02008876 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008877 curproxy->bind_proc |= mask;
8878 }
8879
8880 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008881 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008882 }
8883
8884 if (global.stats_fe) {
8885 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8886 unsigned long mask;
8887
Cyril Bonté06181952016-02-24 00:14:54 +01008888 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008889 global.stats_fe->bind_proc |= mask;
8890 }
8891 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008892 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008893 }
8894
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008895 /* propagate bindings from frontends to backends. Don't do it if there
8896 * are any fatal errors as we must not call it with unresolved proxies.
8897 */
8898 if (!cfgerr) {
8899 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8900 if (curproxy->cap & PR_CAP_FE)
8901 propagate_processes(curproxy, NULL);
8902 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008903 }
8904
8905 /* Bind each unbound backend to all processes when not specified. */
8906 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8907 if (curproxy->bind_proc)
8908 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008909 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008910 }
8911
8912 /*******************************************************/
8913 /* At this step, all proxies have a non-null bind_proc */
8914 /*******************************************************/
8915
8916 /* perform the final checks before creating tasks */
8917
8918 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8919 struct listener *listener;
8920 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008921
Emeric Brunc52962f2012-11-15 18:28:02 +01008922#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008923 /* Configure SSL for each bind line.
8924 * Note: if configuration fails at some point, the ->ctx member
8925 * remains NULL so that listeners can later detach.
8926 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008927 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008928 int alloc_ctx;
8929
Emeric Brunc52962f2012-11-15 18:28:02 +01008930 if (!bind_conf->is_ssl) {
8931 if (bind_conf->default_ctx) {
8932 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8933 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8934 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008935 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008936 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008937 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008938 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008939 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008940 cfgerr++;
8941 continue;
8942 }
8943
Emeric Brun8dc60392014-05-09 13:52:00 +02008944 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008945 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008946 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8947 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
8948 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008949 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008950 cfgerr++;
8951 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008952 }
8953
Emeric Brunfc0421f2012-09-07 17:30:07 +02008954 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008955 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008956
8957 /* initialize CA variables if the certificates generation is enabled */
8958 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008959 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008960#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008961
Willy Tarreaue6b98942007-10-29 01:09:36 +01008962 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008963 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008964 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008965 int nbproc;
8966
8967 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008968 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008969 nbits(global.nbproc));
8970
8971 if (!nbproc) /* no intersection between listener and frontend */
8972 nbproc = 1;
8973
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008974 if (!listener->luid) {
8975 /* listener ID not set, use automatic numbering with first
8976 * spare entry starting with next_luid.
8977 */
8978 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8979 listener->conf.id.key = listener->luid = next_id;
8980 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008981 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008982 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008983
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008984 /* enable separate counters */
8985 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008986 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008987 if (!listener->name)
8988 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008989 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008990
Willy Tarreaue6b98942007-10-29 01:09:36 +01008991 if (curproxy->options & PR_O_TCP_NOLING)
8992 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008993 if (!listener->maxconn)
8994 listener->maxconn = curproxy->maxconn;
8995 if (!listener->backlog)
8996 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008997 if (!listener->maxaccept)
8998 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8999
9000 /* we want to have an optimal behaviour on single process mode to
9001 * maximize the work at once, but in multi-process we want to keep
9002 * some fairness between processes, so we target half of the max
9003 * number of events to be balanced over all the processes the proxy
9004 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9005 * used to disable the limit.
9006 */
9007 if (listener->maxaccept > 0) {
9008 if (nbproc > 1)
9009 listener->maxaccept = (listener->maxaccept + 1) / 2;
9010 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9011 }
9012
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009013 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009014 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009015 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009016 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009017
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009018 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009019 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009020
Willy Tarreau620408f2016-10-21 16:37:51 +02009021 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9022 listener->options |= LI_O_TCP_L5_RULES;
9023
Willy Tarreaude3041d2010-05-31 10:56:17 +02009024 if (curproxy->mon_mask.s_addr)
9025 listener->options |= LI_O_CHK_MONNET;
9026
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009027 /* smart accept mode is automatic in HTTP mode */
9028 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009029 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009030 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9031 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009032 }
9033
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009034 /* Release unused SSL configs */
9035 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
9036 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009037 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009038#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02009039 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009040 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009041 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02009042 free(bind_conf->ca_sign_file);
9043 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009044 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009045 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009046 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009047 if(bind_conf->keys_ref) {
9048 free(bind_conf->keys_ref->filename);
9049 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009050 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009051 free(bind_conf->keys_ref);
9052 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009053#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009054 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009055
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009056 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009057 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009058 int count, maxproc = 0;
9059
9060 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009061 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009062 if (count > maxproc)
9063 maxproc = count;
9064 }
9065 /* backends have 0, frontends have 1 or more */
9066 if (maxproc != 1)
9067 Warning("Proxy '%s': in multi-process mode, stats will be"
9068 " limited to process assigned to the current request.\n",
9069 curproxy->id);
9070
Willy Tarreau102df612014-05-07 23:56:38 +02009071 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9072 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9073 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009074 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009075 }
Willy Tarreau102df612014-05-07 23:56:38 +02009076 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9077 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9078 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009079 }
9080 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009081
9082 /* create the task associated with the proxy */
9083 curproxy->task = task_new();
9084 if (curproxy->task) {
9085 curproxy->task->context = curproxy;
9086 curproxy->task->process = manage_proxy;
9087 /* no need to queue, it will be done automatically if some
9088 * listener gets limited.
9089 */
9090 curproxy->task->expire = TICK_ETERNITY;
9091 } else {
9092 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9093 curproxy->id);
9094 cfgerr++;
9095 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009096 }
9097
Willy Tarreaufbb78422011-06-05 15:38:35 +02009098 /* automatically compute fullconn if not set. We must not do it in the
9099 * loop above because cross-references are not yet fully resolved.
9100 */
9101 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9102 /* If <fullconn> is not set, let's set it to 10% of the sum of
9103 * the possible incoming frontend's maxconns.
9104 */
9105 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9106 struct proxy *fe;
9107 int total = 0;
9108
9109 /* sum up the number of maxconns of frontends which
9110 * reference this backend at least once or which are
9111 * the same one ('listen').
9112 */
9113 for (fe = proxy; fe; fe = fe->next) {
9114 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009115 int found = 0;
9116
9117 if (!(fe->cap & PR_CAP_FE))
9118 continue;
9119
9120 if (fe == curproxy) /* we're on a "listen" instance */
9121 found = 1;
9122
9123 if (fe->defbe.be == curproxy) /* "default_backend" */
9124 found = 1;
9125
9126 /* check if a "use_backend" rule matches */
9127 if (!found) {
9128 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009129 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009130 found = 1;
9131 break;
9132 }
9133 }
9134 }
9135
Willy Tarreaufbb78422011-06-05 15:38:35 +02009136 /* now we've checked all possible ways to reference a backend
9137 * from a frontend.
9138 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009139 if (!found)
9140 continue;
9141 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009142 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009143 /* we have the sum of the maxconns in <total>. We only
9144 * keep 10% of that sum to set the default fullconn, with
9145 * a hard minimum of 1 (to avoid a divide by zero).
9146 */
9147 curproxy->fullconn = (total + 9) / 10;
9148 if (!curproxy->fullconn)
9149 curproxy->fullconn = 1;
9150 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009151 }
9152
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009153 /*
9154 * Recount currently required checks.
9155 */
9156
9157 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9158 int optnum;
9159
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009160 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9161 if (curproxy->options & cfg_opts[optnum].val)
9162 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009163
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009164 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9165 if (curproxy->options2 & cfg_opts2[optnum].val)
9166 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009167 }
9168
Willy Tarreau0fca4832015-05-01 19:12:05 +02009169 /* compute the required process bindings for the peers */
9170 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9171 if (curproxy->table.peers.p)
9172 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9173
Willy Tarreau122541c2011-09-07 21:24:49 +02009174 if (peers) {
9175 struct peers *curpeers = peers, **last;
9176 struct peer *p, *pb;
9177
Willy Tarreau1e273012015-05-01 19:15:17 +02009178 /* Remove all peers sections which don't have a valid listener,
9179 * which are not used by any table, or which are bound to more
9180 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009181 */
9182 last = &peers;
9183 while (*last) {
9184 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009185
9186 if (curpeers->state == PR_STSTOPPED) {
9187 /* the "disabled" keyword was present */
9188 if (curpeers->peers_fe)
9189 stop_proxy(curpeers->peers_fe);
9190 curpeers->peers_fe = NULL;
9191 }
9192 else if (!curpeers->peers_fe) {
9193 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9194 curpeers->id, localpeer);
9195 }
David Carliere6c39412015-07-02 07:00:17 +00009196 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009197 /* either it's totally stopped or too much used */
9198 if (curpeers->peers_fe->bind_proc) {
9199 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009200 "running in different processes (%d different ones). "
9201 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009202 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009203 cfgerr++;
9204 }
9205 stop_proxy(curpeers->peers_fe);
9206 curpeers->peers_fe = NULL;
9207 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009208 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009209 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009210 last = &curpeers->next;
9211 continue;
9212 }
9213
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009214 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009215 p = curpeers->remote;
9216 while (p) {
9217 pb = p->next;
9218 free(p->id);
9219 free(p);
9220 p = pb;
9221 }
9222
9223 /* Destroy and unlink this curpeers section.
9224 * Note: curpeers is backed up into *last.
9225 */
9226 free(curpeers->id);
9227 curpeers = curpeers->next;
9228 free(*last);
9229 *last = curpeers;
9230 }
9231 }
9232
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009233 /* initialize stick-tables on backend capable proxies. This must not
9234 * be done earlier because the data size may be discovered while parsing
9235 * other proxies.
9236 */
9237 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9238 if (curproxy->state == PR_STSTOPPED)
9239 continue;
9240
9241 if (!stktable_init(&curproxy->table)) {
9242 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9243 cfgerr++;
9244 }
9245 }
9246
Simon Horman0d16a402015-01-30 11:22:58 +09009247 if (mailers) {
9248 struct mailers *curmailers = mailers, **last;
9249 struct mailer *m, *mb;
9250
9251 /* Remove all mailers sections which don't have a valid listener.
9252 * This can happen when a mailers section is never referenced.
9253 */
9254 last = &mailers;
9255 while (*last) {
9256 curmailers = *last;
9257 if (curmailers->users) {
9258 last = &curmailers->next;
9259 continue;
9260 }
9261
9262 Warning("Removing incomplete section 'mailers %s'.\n",
9263 curmailers->id);
9264
9265 m = curmailers->mailer_list;
9266 while (m) {
9267 mb = m->next;
9268 free(m->id);
9269 free(m);
9270 m = mb;
9271 }
9272
9273 /* Destroy and unlink this curmailers section.
9274 * Note: curmailers is backed up into *last.
9275 */
9276 free(curmailers->id);
9277 curmailers = curmailers->next;
9278 free(*last);
9279 *last = curmailers;
9280 }
9281 }
9282
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009283 /* Update server_state_file_name to backend name if backend is supposed to use
9284 * a server-state file locally defined and none has been provided */
9285 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9286 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9287 curproxy->server_state_file_name == NULL)
9288 curproxy->server_state_file_name = strdup(curproxy->id);
9289 }
9290
Willy Tarreau34eb6712011-10-24 18:15:04 +02009291 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009292 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009293 MEM_F_SHARED);
9294
Willy Tarreaubb925012009-07-23 13:36:36 +02009295 if (cfgerr > 0)
9296 err_code |= ERR_ALERT | ERR_FATAL;
9297 out:
9298 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009299}
9300
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009301/*
9302 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9303 * parsing sessions.
9304 */
9305void cfg_register_keywords(struct cfg_kw_list *kwl)
9306{
9307 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9308}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009309
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009310/*
9311 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9312 */
9313void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9314{
9315 LIST_DEL(&kwl->list);
9316 LIST_INIT(&kwl->list);
9317}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009318
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009319/* this function register new section in the haproxy configuration file.
9320 * <section_name> is the name of this new section and <section_parser>
9321 * is the called parser. If two section declaration have the same name,
9322 * only the first declared is used.
9323 */
9324int cfg_register_section(char *section_name,
9325 int (*section_parser)(const char *, int, char **, int))
9326{
9327 struct cfg_section *cs;
9328
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009329 list_for_each_entry(cs, &sections, list) {
9330 if (strcmp(cs->section_name, section_name) == 0) {
9331 Alert("register section '%s': already registered.\n", section_name);
9332 return 0;
9333 }
9334 }
9335
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009336 cs = calloc(1, sizeof(*cs));
9337 if (!cs) {
9338 Alert("register section '%s': out of memory.\n", section_name);
9339 return 0;
9340 }
9341
9342 cs->section_name = section_name;
9343 cs->section_parser = section_parser;
9344
9345 LIST_ADDQ(&sections, &cs->list);
9346
9347 return 1;
9348}
9349
Willy Tarreaubaaee002006-06-26 02:48:02 +02009350/*
David Carlier845efb52015-09-25 11:49:18 +01009351 * free all config section entries
9352 */
9353void cfg_unregister_sections(void)
9354{
9355 struct cfg_section *cs, *ics;
9356
9357 list_for_each_entry_safe(cs, ics, &sections, list) {
9358 LIST_DEL(&cs->list);
9359 free(cs);
9360 }
9361}
9362
Christopher Faulet7110b402016-10-26 11:09:44 +02009363void cfg_backup_sections(struct list *backup_sections)
9364{
9365 struct cfg_section *cs, *ics;
9366
9367 list_for_each_entry_safe(cs, ics, &sections, list) {
9368 LIST_DEL(&cs->list);
9369 LIST_ADDQ(backup_sections, &cs->list);
9370 }
9371}
9372
9373void cfg_restore_sections(struct list *backup_sections)
9374{
9375 struct cfg_section *cs, *ics;
9376
9377 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9378 LIST_DEL(&cs->list);
9379 LIST_ADDQ(&sections, &cs->list);
9380 }
9381}
9382
Willy Tarreau659fbf02016-05-26 17:55:28 +02009383__attribute__((constructor))
9384static void cfgparse_init(void)
9385{
9386 /* Register internal sections */
9387 cfg_register_section("listen", cfg_parse_listen);
9388 cfg_register_section("frontend", cfg_parse_listen);
9389 cfg_register_section("backend", cfg_parse_listen);
9390 cfg_register_section("defaults", cfg_parse_listen);
9391 cfg_register_section("global", cfg_parse_global);
9392 cfg_register_section("userlist", cfg_parse_users);
9393 cfg_register_section("peers", cfg_parse_peers);
9394 cfg_register_section("mailers", cfg_parse_mailers);
9395 cfg_register_section("namespace_list", cfg_parse_netns);
9396 cfg_register_section("resolvers", cfg_parse_resolvers);
9397}
9398
David Carlier845efb52015-09-25 11:49:18 +01009399/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009400 * Local variables:
9401 * c-indent-level: 8
9402 * c-basic-offset: 8
9403 * End:
9404 */