blob: e69a4ab78b8da4edc1c38e5df0129d27fcdcbb31 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020076#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100205char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100241 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200288 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200291 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200298 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100325 * Report an error in <msg> when there are too many arguments. This version is
326 * intended to be used by keyword parsers so that the message will be included
327 * into the general error message. The index is the current keyword in args.
328 * Return 0 if the number of argument is correct, otherwise build a message and
329 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
330 * message may also be null, it will simply not be produced (useful to check only).
331 * <msg> and <err_code> are only affected on error.
332 */
333int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
334{
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 if (msg) {
341 *msg = NULL;
342 memprintf(msg, "%s", args[0]);
343 for (i = 1; i <= index; i++)
344 memprintf(msg, "%s %s", *msg, args[i]);
345
346 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
347 }
348 if (err_code)
349 *err_code |= ERR_ALERT | ERR_FATAL;
350
351 return 1;
352}
353
354/*
355 * same as too_many_args_idx with a 0 index
356 */
357int too_many_args(int maxarg, char **args, char **msg, int *err_code)
358{
359 return too_many_args_idx(maxarg, 0, args, msg, err_code);
360}
361
362/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200363 * Report a fatal Alert when there is too much arguments
364 * The index is the current keyword in args
365 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
366 * Fill err_code with an ERR_ALERT and an ERR_FATAL
367 */
368int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
369{
370 char *kw = NULL;
371 int i;
372
373 if (!*args[index + maxarg + 1])
374 return 0;
375
376 memprintf(&kw, "%s", args[0]);
377 for (i = 1; i <= index; i++) {
378 memprintf(&kw, "%s %s", kw, args[i]);
379 }
380
381 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
382 free(kw);
383 *err_code |= ERR_ALERT | ERR_FATAL;
384 return 1;
385}
386
387/*
388 * same as alertif_too_many_args_idx with a 0 index
389 */
390int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
391{
392 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
393}
394
Willy Tarreau620408f2016-10-21 16:37:51 +0200395/* Report a warning if a rule is placed after a 'tcp-request session' rule.
396 * Return 1 if the warning has been emitted, otherwise 0.
397 */
398int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
399{
400 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
401 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
402 file, line, arg);
403 return 1;
404 }
405 return 0;
406}
407
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200408/* Report a warning if a rule is placed after a 'tcp-request content' rule.
409 * Return 1 if the warning has been emitted, otherwise 0.
410 */
411int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
412{
413 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
414 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
415 file, line, arg);
416 return 1;
417 }
418 return 0;
419}
420
Willy Tarreau61d18892009-03-31 10:49:21 +0200421/* Report a warning if a rule is placed after a 'block' rule.
422 * Return 1 if the warning has been emitted, otherwise 0.
423 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100424int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200425{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200426 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200427 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
428 file, line, arg);
429 return 1;
430 }
431 return 0;
432}
433
Willy Tarreau5002f572014-04-23 01:32:02 +0200434/* Report a warning if a rule is placed after an 'http_request' rule.
435 * Return 1 if the warning has been emitted, otherwise 0.
436 */
437int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
438{
439 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
440 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
441 file, line, arg);
442 return 1;
443 }
444 return 0;
445}
446
Willy Tarreau61d18892009-03-31 10:49:21 +0200447/* Report a warning if a rule is placed after a reqrewrite rule.
448 * Return 1 if the warning has been emitted, otherwise 0.
449 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
452 if (proxy->req_exp) {
453 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
454 file, line, arg);
455 return 1;
456 }
457 return 0;
458}
459
460/* Report a warning if a rule is placed after a reqadd rule.
461 * Return 1 if the warning has been emitted, otherwise 0.
462 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100463int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200464{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100465 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
467 file, line, arg);
468 return 1;
469 }
470 return 0;
471}
472
473/* Report a warning if a rule is placed after a redirect rule.
474 * Return 1 if the warning has been emitted, otherwise 0.
475 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
479 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
480 file, line, arg);
481 return 1;
482 }
483 return 0;
484}
485
486/* Report a warning if a rule is placed after a 'use_backend' rule.
487 * Return 1 if the warning has been emitted, otherwise 0.
488 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
491 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
492 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
493 file, line, arg);
494 return 1;
495 }
496 return 0;
497}
498
Willy Tarreauee445d92014-04-23 01:39:04 +0200499/* Report a warning if a rule is placed after a 'use-server' rule.
500 * Return 1 if the warning has been emitted, otherwise 0.
501 */
502int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
503{
504 if (!LIST_ISEMPTY(&proxy->server_rules)) {
505 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
506 file, line, arg);
507 return 1;
508 }
509 return 0;
510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a redirect rule is dangerously placed */
513int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200516 warnif_rule_after_use_server(proxy, file, line, arg);
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a reqadd rule is dangerously placed */
520int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_redirect(proxy, file, line, arg) ||
523 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqxxx rule is dangerously placed */
527int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
530 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200531}
532
533/* report a warning if an http-request rule is dangerously placed */
534int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
535{
Willy Tarreau61d18892009-03-31 10:49:21 +0200536 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100537 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a block rule is dangerously placed */
541int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_http_req(proxy, file, line, arg) ||
544 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a "tcp request content" rule is dangerously placed */
548int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_block(proxy, file, line, arg) ||
551 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request session" rule is dangerously placed */
555int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
558 warnif_misplaced_tcp_cont(proxy, file, line, arg);
559}
560
561/* report a warning if a "tcp request connection" rule is dangerously placed */
562int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
563{
564 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200566}
567
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568/* Report it if a request ACL condition uses some keywords that are incompatible
569 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
570 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
571 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 return 0;
580
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 acl = acl_cond_conflicts(cond, where);
582 if (acl) {
583 if (acl->name && *acl->name)
584 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
585 file, line, acl->name, sample_ckp_names(where));
586 else
587 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200588 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 return ERR_WARN;
590 }
591 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100592 return 0;
593
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 if (acl->name && *acl->name)
595 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200596 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100597 else
598 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200599 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100600 return ERR_WARN;
601}
602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 * parse a line in a <global> section. Returns the error code, 0 if OK, or
605 * any combination of :
606 * - ERR_ABORT: must abort ASAP
607 * - ERR_FATAL: we can continue parsing but not start the service
608 * - ERR_WARN: a warning has been emitted
609 * - ERR_ALERT: an alert has been emitted
610 * Only the two first ones can stop processing, the two others are just
611 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200613int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614{
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200616 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
618 if (!strcmp(args[0], "global")) { /* new section */
619 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200620 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200624 if (alertif_too_many_args(0, file, linenum, args, &err_code))
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 global.mode |= MODE_DAEMON;
627 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200628 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200631 if (*args[1]) {
632 if (!strcmp(args[1], "exit-on-failure")) {
633 global.tune.options |= GTUNE_EXIT_ONFAILURE;
634 } else {
635 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
638 }
639 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200640 global.mode |= MODE_MWORKER;
641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 global.mode |= MODE_DEBUG;
646 }
647 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100660 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100665 global.tune.options &= ~GTUNE_USE_SPLICE;
666 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200670 global.tune.options &= ~GTUNE_USE_GAI;
671 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000672 else if (!strcmp(args[0], "noreuseport")) {
673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
675 global.tune.options &= ~GTUNE_USE_REUSEPORT;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_QUIET;
681 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 if (global.tune.maxpollevents != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200694 }
695 global.tune.maxpollevents = atol(args[1]);
696 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 if (global.tune.maxaccept != 0) {
701 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100709 }
710 global.tune.maxaccept = atol(args[1]);
711 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.chksize = atol(args[1]);
721 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100722 else if (!strcmp(args[0], "tune.recv_enough")) {
723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.recv_enough = atol(args[1]);
731 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.buf_limit = atol(args[1]);
741 if (global.tune.buf_limit) {
742 if (global.tune.buf_limit < 3)
743 global.tune.buf_limit = 3;
744 if (global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
746 }
747 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100748 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.reserved_bufs = atol(args[1]);
757 if (global.tune.reserved_bufs < 2)
758 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100759 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
760 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200771 if (global.tune.bufsize <= 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100776 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100777 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
779 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200788 if (global.tune.maxrewrite < 0) {
789 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200793 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100794 else if (!strcmp(args[0], "tune.idletimer")) {
795 unsigned int idle;
796 const char *res;
797
William Lallemand1a748ae2015-05-19 16:37:23 +0200798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
799 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805
806 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
807 if (res) {
808 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
809 file, linenum, *res, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813
814 if (idle > 65535) {
815 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.idle_timer = idle;
820 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.client_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.client_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.server_rcvbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.server_rcvbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.client_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.client_sndbuf = atol(args[1]);
865 }
866 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100869 if (global.tune.server_sndbuf != 0) {
870 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT;
872 goto out;
873 }
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.server_sndbuf = atol(args[1]);
880 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200881 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.pipesize = atol(args[1]);
890 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100891 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.cookie_len = atol(args[1]) + 1;
900 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200901 else if (!strcmp(args[0], "tune.http.logurilen")) {
902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.requri_len = atol(args[1]) + 1;
910 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200911 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200919 global.tune.max_http_hdr = atoi(args[1]);
920 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
921 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200926 }
William Lallemandf3747832012-11-09 12:33:10 +0100927 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100930 if (*args[1]) {
931 global.tune.comp_maxlevel = atoi(args[1]);
932 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
933 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 } else {
939 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
940 file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200945 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
946 if (*args[1]) {
947 global.tune.pattern_cache = atoi(args[1]);
948 if (global.tune.pattern_cache < 0) {
949 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
950 file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 } else {
955 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
956 file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200965 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100974 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
975 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
976 err_code |= ERR_WARN;
977 goto out;
978 }
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100994 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
995 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
996 err_code |= ERR_WARN;
997 goto out;
998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
Simon Horman98637e52014-06-20 12:30:16 +09001000 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1002 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001003 global.external_check = 1;
1004 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001005 /* user/group name handling */
1006 else if (!strcmp(args[0], "user")) {
1007 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001008 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1009 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001010 if (global.uid != 0) {
1011 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT;
1013 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001014 }
1015 errno = 0;
1016 ha_user = getpwnam(args[1]);
1017 if (ha_user != NULL) {
1018 global.uid = (int)ha_user->pw_uid;
1019 }
1020 else {
1021 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001023 }
1024 }
1025 else if (!strcmp(args[0], "group")) {
1026 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001027 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1028 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001029 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001030 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT;
1032 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 }
1034 errno = 0;
1035 ha_group = getgrnam(args[1]);
1036 if (ha_group != NULL) {
1037 global.gid = (int)ha_group->gr_gid;
1038 }
1039 else {
1040 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001042 }
1043 }
1044 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001054 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1055 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1056 file, linenum, args[0], LONGBITS, global.nbproc);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.maxconn != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.maxconn = atol(args[1]);
1075#ifdef SYSTEM_MAXCONN
1076 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1077 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1078 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081#endif /* SYSTEM_MAXCONN */
1082 }
Emeric Brun850efd52014-01-29 12:24:34 +01001083 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 if (strcmp(args[1],"none") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1093 else if (strcmp(args[1],"required") == 0)
1094 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1095 else {
1096 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001101 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1103 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001104 if (global.cps_lim != 0) {
1105 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT;
1107 goto out;
1108 }
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 global.cps_lim = atol(args[1]);
1115 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001116 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001119 if (global.sps_lim != 0) {
1120 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT;
1122 goto out;
1123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
1128 }
1129 global.sps_lim = atol(args[1]);
1130 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001131 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1133 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001134 if (global.ssl_lim != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1136 err_code |= ERR_ALERT;
1137 goto out;
1138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
1143 }
1144 global.ssl_lim = atol(args[1]);
1145 }
William Lallemandd85f9172012-11-09 17:05:39 +01001146 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
1153 }
1154 global.comp_rate_lim = atoi(args[1]) * 1024;
1155 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001156 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001159 if (global.maxpipes != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001168 }
1169 global.maxpipes = atol(args[1]);
1170 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001171 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
William Lallemande3a7d992012-11-20 11:25:20 +01001179 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001180 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001181 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001190 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001191 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (global.rlimit_nofile != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
1210 global.rlimit_nofile = atol(args[1]);
1211 }
1212 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 if (global.chroot != NULL) {
1216 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001217 err_code |= ERR_ALERT;
1218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 }
1225 global.chroot = strdup(args[1]);
1226 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001227 else if (!strcmp(args[0], "description")) {
1228 int i, len=0;
1229 char *d;
1230
1231 if (!*args[1]) {
1232 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1233 file, linenum, args[0]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
Willy Tarreau348acfe2014-04-14 15:00:39 +02001238 for (i = 1; *args[i]; i++)
1239 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001240
1241 if (global.desc)
1242 free(global.desc);
1243
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001244 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001245
Willy Tarreau348acfe2014-04-14 15:00:39 +02001246 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1247 for (i = 2; *args[i]; i++)
1248 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001249 }
1250 else if (!strcmp(args[0], "node")) {
1251 int i;
1252 char c;
1253
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
1256
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001257 for (i=0; args[1][i]; i++) {
1258 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001259 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1260 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001261 break;
1262 }
1263
1264 if (!i || args[1][i]) {
1265 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1266 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1267 file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if (global.node)
1273 free(global.node);
1274
1275 global.node = strdup(args[1]);
1276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (global.pidfile != NULL) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001282 err_code |= ERR_ALERT;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
1290 global.pidfile = strdup(args[1]);
1291 }
Emeric Bruned760922010-10-22 17:59:25 +02001292 else if (!strcmp(args[0], "unix-bind")) {
1293 int cur_arg = 1;
1294 while (*(args[cur_arg])) {
1295 if (!strcmp(args[cur_arg], "prefix")) {
1296 if (global.unix_bind.prefix != NULL) {
1297 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1298 err_code |= ERR_ALERT;
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (*(args[cur_arg+1]) == 0) {
1304 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "mode")) {
1314
1315 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1316 cur_arg += 2;
1317 continue;
1318 }
1319
1320 if (!strcmp(args[cur_arg], "uid")) {
1321
1322 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1323 cur_arg += 2;
1324 continue;
1325 }
1326
1327 if (!strcmp(args[cur_arg], "gid")) {
1328
1329 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1330 cur_arg += 2;
1331 continue;
1332 }
1333
1334 if (!strcmp(args[cur_arg], "user")) {
1335 struct passwd *user;
1336
1337 user = getpwnam(args[cur_arg + 1]);
1338 if (!user) {
1339 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1340 file, linenum, args[0], args[cur_arg + 1 ]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 global.unix_bind.ux.uid = user->pw_uid;
1346 cur_arg += 2;
1347 continue;
1348 }
1349
1350 if (!strcmp(args[cur_arg], "group")) {
1351 struct group *group;
1352
1353 group = getgrnam(args[cur_arg + 1]);
1354 if (!group) {
1355 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1356 file, linenum, args[0], args[cur_arg + 1 ]);
1357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
1359 }
1360
1361 global.unix_bind.ux.gid = group->gr_gid;
1362 cur_arg += 2;
1363 continue;
1364 }
1365
Willy Tarreaub48f9582011-09-05 01:17:06 +02001366 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1373 /* delete previous herited or defined syslog servers */
1374 struct logsrv *back;
1375 struct logsrv *tmp;
1376
1377 if (*(args[1]) != 0) {
1378 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
1382
1383 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1384 LIST_DEL(&tmp->list);
1385 free(tmp);
1386 }
1387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001389 struct sockaddr_storage *sk;
1390 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001392 int arg = 0;
1393 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001394
William Lallemand1a748ae2015-05-19 16:37:23 +02001395 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1396 goto out;
1397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 if (*(args[1]) == 0 || *(args[2]) == 0) {
1399 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Vincent Bernat02779b62016-04-03 13:48:43 +02001404 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001405
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 /* just after the address, a length may be specified */
1407 if (strcmp(args[arg+2], "len") == 0) {
1408 len = atoi(args[arg+3]);
1409 if (len < 80 || len > 65535) {
1410 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1411 file, linenum, args[arg+3]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415 logsrv->maxlen = len;
1416
1417 /* skip these two args */
1418 arg += 2;
1419 }
1420 else
1421 logsrv->maxlen = MAX_SYSLOG_LEN;
1422
1423 if (logsrv->maxlen > global.max_syslog_len) {
1424 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001425 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1426 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1427 logline = my_realloc2(logline, global.max_syslog_len + 1);
1428 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001429 }
1430
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 /* after the length, a format may be specified */
1432 if (strcmp(args[arg+2], "format") == 0) {
1433 logsrv->format = get_log_format(args[arg+3]);
1434 if (logsrv->format < 0) {
1435 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001437 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001438 goto out;
1439 }
1440
1441 /* skip these two args */
1442 arg += 2;
1443 }
1444
David Carlier97880bb2016-04-08 10:35:26 +01001445 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1446 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001447 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001448 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001449
Willy Tarreau18324f52014-06-27 18:10:07 +02001450 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001451 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001452 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001453 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001454 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001458 if (*(args[arg+3])) {
1459 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001460 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001463 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 }
1466
William Lallemand0f99e342011-10-12 17:50:54 +02001467 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001468 if (*(args[arg+4])) {
1469 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001470 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001471 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001472 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001473 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001474 }
1475 }
1476
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001477 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001478 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001479 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001481 free(logsrv);
1482 goto out;
1483 }
1484 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001485
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001486 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487 if (port1 != port2) {
1488 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1489 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001490 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001491 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001492 goto out;
1493 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001494
William Lallemand0f99e342011-10-12 17:50:54 +02001495 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001496 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001497 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
William Lallemand0f99e342011-10-12 17:50:54 +02001500 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001501 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001502 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1503 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001504
1505 if (global.log_send_hostname != NULL) {
1506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1507 err_code |= ERR_ALERT;
1508 goto out;
1509 }
1510
1511 if (*(args[1]))
1512 name = args[1];
1513 else
1514 name = hostname;
1515
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001516 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001517 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001518 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001519 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1520 if (global.server_state_base != NULL) {
1521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1522 err_code |= ERR_ALERT;
1523 goto out;
1524 }
1525
1526 if (!*(args[1])) {
1527 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1528 err_code |= ERR_FATAL;
1529 goto out;
1530 }
1531
1532 global.server_state_base = strdup(args[1]);
1533 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001534 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1535 if (global.server_state_file != NULL) {
1536 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1537 err_code |= ERR_ALERT;
1538 goto out;
1539 }
1540
1541 if (!*(args[1])) {
1542 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1543 err_code |= ERR_FATAL;
1544 goto out;
1545 }
1546
1547 global.server_state_file = strdup(args[1]);
1548 }
Kevinm48936af2010-12-22 16:08:21 +00001549 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001550 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1551 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001552 if (*(args[1]) == 0) {
1553 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001557 chunk_destroy(&global.log_tag);
1558 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001559 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1562 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001563 if (global.spread_checks != 0) {
1564 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001565 err_code |= ERR_ALERT;
1566 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001567 }
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001572 }
1573 global.spread_checks = atol(args[1]);
1574 if (global.spread_checks < 0 || global.spread_checks > 50) {
1575 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001579 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1580 const char *err;
1581 unsigned int val;
1582
William Lallemand1a748ae2015-05-19 16:37:23 +02001583 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1584 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001585 if (*(args[1]) == 0) {
1586 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1592 if (err) {
1593 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 }
1596 global.max_spread_checks = val;
1597 if (global.max_spread_checks < 0) {
1598 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 }
1601 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001602 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1603#ifdef USE_CPU_AFFINITY
1604 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001605 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 unsigned long cpus = 0;
1607
1608 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001611 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 proc = atol(args[1]);
1616 if (proc >= 1 && proc <= LONGBITS)
1617 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001618 }
1619
1620 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1622 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
1627 cur_arg = 2;
1628 while (*args[cur_arg]) {
1629 unsigned int low, high;
1630
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001631 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001632 char *dash = strchr(args[cur_arg], '-');
1633
1634 low = high = str2uic(args[cur_arg]);
1635 if (dash)
1636 high = str2uic(dash + 1);
1637
1638 if (high < low) {
1639 unsigned int swap = low;
1640 low = high;
1641 high = swap;
1642 }
1643
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001644 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001645 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001646 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
1649 }
1650
1651 while (low <= high)
1652 cpus |= 1UL << low++;
1653 }
1654 else {
1655 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1656 file, linenum, args[0], args[cur_arg]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660 cur_arg++;
1661 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001662 for (i = 0; i < LONGBITS; i++)
1663 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001664 global.cpu_map[i] = cpus;
1665#else
1666 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669#endif
1670 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001671 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1672 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1673 goto out;
1674
1675 if (*(args[2]) == 0) {
1676 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680
1681 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1682 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1683 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687 }
1688 else if (!strcmp(args[0], "unsetenv")) {
1689 int arg;
1690
1691 if (*(args[1]) == 0) {
1692 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
1697 for (arg = 1; *args[arg]; arg++) {
1698 if (unsetenv(args[arg]) != 0) {
1699 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703 }
1704 }
1705 else if (!strcmp(args[0], "resetenv")) {
1706 extern char **environ;
1707 char **env = environ;
1708
1709 /* args contain variable names to keep, one per argument */
1710 while (*env) {
1711 int arg;
1712
1713 /* look for current variable in among all those we want to keep */
1714 for (arg = 1; *args[arg]; arg++) {
1715 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1716 (*env)[strlen(args[arg])] == '=')
1717 break;
1718 }
1719
1720 /* delete this variable */
1721 if (!*args[arg]) {
1722 char *delim = strchr(*env, '=');
1723
1724 if (!delim || delim - *env >= trash.size) {
1725 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
1730 memcpy(trash.str, *env, delim - *env);
1731 trash.str[delim - *env] = 0;
1732
1733 if (unsetenv(trash.str) != 0) {
1734 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
1737 }
1738 }
1739 else
1740 env++;
1741 }
1742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001744 struct cfg_kw_list *kwl;
1745 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001746 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001747
1748 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1749 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1750 if (kwl->kw[index].section != CFG_GLOBAL)
1751 continue;
1752 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001753 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001754 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001755 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001758 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001759 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001760 err_code |= ERR_WARN;
1761 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001762 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001764 }
1765 }
1766 }
1767
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001771
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001773 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001774 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775}
1776
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001777void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001779 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 defproxy.mode = PR_MODE_TCP;
1781 defproxy.state = PR_STNEW;
1782 defproxy.maxconn = cfg_maxpconn;
1783 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001784 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001785 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001786
Simon Horman66183002013-02-23 10:16:43 +09001787 defproxy.defsrv.check.inter = DEF_CHKINTR;
1788 defproxy.defsrv.check.fastinter = 0;
1789 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001790 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1791 defproxy.defsrv.agent.fastinter = 0;
1792 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001793 defproxy.defsrv.check.rise = DEF_RISETIME;
1794 defproxy.defsrv.check.fall = DEF_FALLTIME;
1795 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1796 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001797 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001798 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 defproxy.defsrv.maxqueue = 0;
1800 defproxy.defsrv.minconn = 0;
1801 defproxy.defsrv.maxconn = 0;
1802 defproxy.defsrv.slowstart = 0;
1803 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1804 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1805 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001806
1807 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001808 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809}
1810
Willy Tarreauade5ec42010-01-28 19:33:49 +01001811
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1813 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1814 * ERR_FATAL in case of error.
1815 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816static int create_cond_regex_rule(const char *file, int line,
1817 struct proxy *px, int dir, int action, int flags,
1818 const char *cmd, const char *reg, const char *repl,
1819 const char **cond_start)
1820{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001822 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001826 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001827 int cs;
1828 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001829
1830 if (px == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833 goto err;
1834 }
1835
1836 if (*reg == 0) {
1837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001838 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001839 goto err;
1840 }
1841
Christopher Faulet898566e2016-10-26 11:06:28 +02001842 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001844
Willy Tarreau5321c422010-01-28 20:35:13 +01001845 if (cond_start &&
1846 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001847 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1848 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1849 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 goto err;
1852 }
1853 }
1854 else if (cond_start && **cond_start) {
1855 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1856 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001858 goto err;
1859 }
1860
Willy Tarreau63af98d2014-05-18 08:11:41 +02001861 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001862 (dir == SMP_OPT_DIR_REQ) ?
1863 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1864 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1865 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868 if (!preg) {
1869 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001870 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871 goto err;
1872 }
1873
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 cs = !(flags & REG_ICASE);
1875 cap = !(flags & REG_NOSUB);
1876 error = NULL;
1877 if (!regex_comp(reg, preg, cs, cap, &error)) {
1878 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1879 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001880 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881 goto err;
1882 }
1883
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001884 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001885 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886 if (repl && err) {
1887 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1888 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001889 ret_code |= ERR_ALERT | ERR_FATAL;
1890 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891 }
1892
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001893 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_WARN;
1895
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900 err:
1901 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001902 free(errmsg);
1903 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904}
1905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906/*
William Lallemand51097192015-04-14 16:35:22 +02001907 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001908 * Returns the error code, 0 if OK, or any combination of :
1909 * - ERR_ABORT: must abort ASAP
1910 * - ERR_FATAL: we can continue parsing but not start the service
1911 * - ERR_WARN: a warning has been emitted
1912 * - ERR_ALERT: an alert has been emitted
1913 * Only the two first ones can stop processing, the two others are just
1914 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001916int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1917{
1918 static struct peers *curpeers = NULL;
1919 struct peer *newpeer = NULL;
1920 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001921 struct bind_conf *bind_conf;
1922 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001924 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
1926 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001927 if (!*args[1]) {
1928 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001929 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 goto out;
1931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001932
William Lallemand6e62fb62015-04-28 16:55:23 +02001933 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1934 goto out;
1935
Emeric Brun32da3c42010-09-23 18:39:19 +02001936 err = invalid_char(args[1]);
1937 if (err) {
1938 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1939 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001940 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001941 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 }
1943
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001944 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001945 /*
1946 * If there are two proxies with the same name only following
1947 * combinations are allowed:
1948 */
1949 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001950 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001951 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001953 }
1954 }
1955
Vincent Bernat02779b62016-04-03 13:48:43 +02001956 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1958 err_code |= ERR_ALERT | ERR_ABORT;
1959 goto out;
1960 }
1961
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001962 curpeers->next = cfg_peers;
1963 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001964 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 curpeers->conf.line = linenum;
1966 curpeers->last_change = now.tv_sec;
1967 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001968 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001969 }
1970 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001971 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001972 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001973 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001974
1975 if (!*args[2]) {
1976 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1977 file, linenum, args[0]);
1978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
1980 }
1981
1982 err = invalid_char(args[1]);
1983 if (err) {
1984 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1985 file, linenum, *err, args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
Vincent Bernat02779b62016-04-03 13:48:43 +02001990 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1992 err_code |= ERR_ALERT | ERR_ABORT;
1993 goto out;
1994 }
1995
1996 /* the peers are linked backwards first */
1997 curpeers->count++;
1998 newpeer->next = curpeers->remote;
1999 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002000 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 newpeer->conf.line = linenum;
2002
2003 newpeer->last_change = now.tv_sec;
2004 newpeer->id = strdup(args[1]);
2005
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002006 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002007 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002008 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002011 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002012
2013 proto = protocol_by_family(sk->ss_family);
2014 if (!proto || !proto->connect) {
2015 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2016 file, linenum, args[0], args[1]);
2017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002020
2021 if (port1 != port2) {
2022 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2023 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
2027
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028 if (!port1) {
2029 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2030 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002037 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002038 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002039
Emeric Brun32da3c42010-09-23 18:39:19 +02002040 if (strcmp(newpeer->id, localpeer) == 0) {
2041 /* Current is local peer, it define a frontend */
2042 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002043 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
2045 if (!curpeers->peers_fe) {
2046 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2048 err_code |= ERR_ALERT | ERR_ABORT;
2049 goto out;
2050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
Willy Tarreau237250c2011-07-29 01:49:03 +02002052 init_new_proxy(curpeers->peers_fe);
2053 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002054 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002055 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2056 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002057 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002059 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060
Willy Tarreau902636f2013-03-10 19:44:48 +01002061 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2062 if (errmsg && *errmsg) {
2063 indent_msg(&errmsg, 2);
2064 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002065 }
2066 else
2067 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2068 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 err_code |= ERR_FATAL;
2070 goto out;
2071 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002072
2073 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002074 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002075 l->maxconn = curpeers->peers_fe->maxconn;
2076 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002077 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002078 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002079 l->analysers |= curpeers->peers_fe->fe_req_ana;
2080 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002081 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2082 global.maxsock += l->maxconn;
2083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002085 else {
2086 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2087 file, linenum, args[0], args[1],
2088 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2089 err_code |= ERR_FATAL;
2090 goto out;
2091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 }
2093 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002094 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2095 curpeers->state = PR_STSTOPPED;
2096 }
2097 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2098 curpeers->state = PR_STNEW;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 else if (*args[0] != 0) {
2101 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
2105
2106out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002107 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 return err_code;
2109}
2110
Baptiste Assmann325137d2015-04-13 23:40:55 +02002111/*
2112 * Parse a <resolvers> section.
2113 * Returns the error code, 0 if OK, or any combination of :
2114 * - ERR_ABORT: must abort ASAP
2115 * - ERR_FATAL: we can continue parsing but not start the service
2116 * - ERR_WARN: a warning has been emitted
2117 * - ERR_ALERT: an alert has been emitted
2118 * Only the two first ones can stop processing, the two others are just
2119 * indicators.
2120 */
2121int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2122{
2123 static struct dns_resolvers *curr_resolvers = NULL;
2124 struct dns_nameserver *newnameserver = NULL;
2125 const char *err;
2126 int err_code = 0;
2127 char *errmsg = NULL;
2128
2129 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2139 file, linenum, *err, args[0], args[1]);
2140 err_code |= ERR_ALERT | ERR_ABORT;
2141 goto out;
2142 }
2143
2144 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2145 /* Error if two resolvers owns the same name */
2146 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2147 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2148 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 }
2151 }
2152
Vincent Bernat02779b62016-04-03 13:48:43 +02002153 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2155 err_code |= ERR_ALERT | ERR_ABORT;
2156 goto out;
2157 }
2158
2159 /* default values */
2160 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2161 curr_resolvers->conf.file = strdup(file);
2162 curr_resolvers->conf.line = linenum;
2163 curr_resolvers->id = strdup(args[1]);
2164 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002165 /* default maximum response size */
2166 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002167 /* default hold period for nx, other, refuse and timeout is 30s */
2168 curr_resolvers->hold.nx = 30000;
2169 curr_resolvers->hold.other = 30000;
2170 curr_resolvers->hold.refused = 30000;
2171 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002172 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002173 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002174 curr_resolvers->hold.valid = 10000;
2175 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002177 /* default resolution pool size */
2178 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002179 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002180 LIST_INIT(&curr_resolvers->resolution.curr);
2181 LIST_INIT(&curr_resolvers->resolution.wait);
2182 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002183 }
2184 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2185 struct sockaddr_storage *sk;
2186 int port1, port2;
2187 struct protocol *proto;
2188
2189 if (!*args[2]) {
2190 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2191 file, linenum, args[0]);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 err = invalid_char(args[1]);
2197 if (err) {
2198 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2199 file, linenum, *err, args[1]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Baptiste Assmanna315c552015-11-02 22:55:49 +01002204 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2205 /* Error if two resolvers owns the same name */
2206 if (strcmp(newnameserver->id, args[1]) == 0) {
2207 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2208 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 }
2211 }
2212
Vincent Bernat02779b62016-04-03 13:48:43 +02002213 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2215 err_code |= ERR_ALERT | ERR_ABORT;
2216 goto out;
2217 }
2218
2219 /* the nameservers are linked backward first */
2220 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2221 curr_resolvers->count_nameservers++;
2222 newnameserver->resolvers = curr_resolvers;
2223 newnameserver->conf.file = strdup(file);
2224 newnameserver->conf.line = linenum;
2225 newnameserver->id = strdup(args[1]);
2226
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002227 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002228 if (!sk) {
2229 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234 proto = protocol_by_family(sk->ss_family);
2235 if (!proto || !proto->connect) {
2236 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2237 file, linenum, args[0], args[1]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
2241
2242 if (port1 != port2) {
2243 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2244 file, linenum, args[0], args[1], args[2]);
2245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
2247 }
2248
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002249 if (!port1 && !port2) {
2250 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2251 file, linenum, args[0], args[1]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 newnameserver->addr = *sk;
2257 }
2258 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2259 const char *res;
2260 unsigned int time;
2261
2262 if (!*args[2]) {
2263 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2264 file, linenum, args[0]);
2265 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2270 if (res) {
2271 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2272 file, linenum, *res, args[0]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002276 if (strcmp(args[1], "nx") == 0)
2277 curr_resolvers->hold.nx = time;
2278 else if (strcmp(args[1], "other") == 0)
2279 curr_resolvers->hold.other = time;
2280 else if (strcmp(args[1], "refused") == 0)
2281 curr_resolvers->hold.refused = time;
2282 else if (strcmp(args[1], "timeout") == 0)
2283 curr_resolvers->hold.timeout = time;
2284 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002285 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002286 else if (strcmp(args[1], "obsolete") == 0)
2287 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002289 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002290 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002296 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002297 int i = 0;
2298
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002299 if (!*args[1]) {
2300 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2301 file, linenum, args[0]);
2302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002305
2306 i = atoi(args[1]);
2307 if (i > DNS_MAX_UDP_MESSAGE) {
2308 Alert("parsing [%s:%d] : '%s' size %d exceeds maximum allowed size %d.\n",
2309 file, linenum, args[0], i, DNS_MAX_UDP_MESSAGE);
2310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
2312 }
2313
2314 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002315 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002316 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2317 if (!*args[1]) {
2318 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2319 file, linenum, args[0]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323 curr_resolvers->resolution_pool_size = atoi(args[1]);
2324 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002325 else if (strcmp(args[0], "resolve_retries") == 0) {
2326 if (!*args[1]) {
2327 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2328 file, linenum, args[0]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332 curr_resolvers->resolve_retries = atoi(args[1]);
2333 }
2334 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002335 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002336 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2337 file, linenum, args[0]);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002341 else if (strcmp(args[1], "retry") == 0) {
2342 const char *res;
2343 unsigned int timeout_retry;
2344
2345 if (!*args[2]) {
2346 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2347 file, linenum, args[0], args[1]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2352 if (res) {
2353 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2354 file, linenum, *res, args[0], args[1]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358 curr_resolvers->timeout.retry = timeout_retry;
2359 }
2360 else {
2361 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2362 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002366 } /* neither "nameserver" nor "resolvers" */
2367 else if (*args[0] != 0) {
2368 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
2371 }
2372
2373 out:
2374 free(errmsg);
2375 return err_code;
2376}
Simon Horman0d16a402015-01-30 11:22:58 +09002377
2378/*
William Lallemand51097192015-04-14 16:35:22 +02002379 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002380 * Returns the error code, 0 if OK, or any combination of :
2381 * - ERR_ABORT: must abort ASAP
2382 * - ERR_FATAL: we can continue parsing but not start the service
2383 * - ERR_WARN: a warning has been emitted
2384 * - ERR_ALERT: an alert has been emitted
2385 * Only the two first ones can stop processing, the two others are just
2386 * indicators.
2387 */
2388int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2389{
2390 static struct mailers *curmailers = NULL;
2391 struct mailer *newmailer = NULL;
2392 const char *err;
2393 int err_code = 0;
2394 char *errmsg = NULL;
2395
2396 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2397 if (!*args[1]) {
2398 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2399 err_code |= ERR_ALERT | ERR_ABORT;
2400 goto out;
2401 }
2402
2403 err = invalid_char(args[1]);
2404 if (err) {
2405 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2406 file, linenum, *err, args[0], args[1]);
2407 err_code |= ERR_ALERT | ERR_ABORT;
2408 goto out;
2409 }
2410
2411 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2412 /*
2413 * If there are two proxies with the same name only following
2414 * combinations are allowed:
2415 */
2416 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002417 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 +09002418 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002420 }
2421 }
2422
Vincent Bernat02779b62016-04-03 13:48:43 +02002423 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002424 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2425 err_code |= ERR_ALERT | ERR_ABORT;
2426 goto out;
2427 }
2428
2429 curmailers->next = mailers;
2430 mailers = curmailers;
2431 curmailers->conf.file = strdup(file);
2432 curmailers->conf.line = linenum;
2433 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002434 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2435 * But need enough time so that timeouts don't occur
2436 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002437 }
2438 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2439 struct sockaddr_storage *sk;
2440 int port1, port2;
2441 struct protocol *proto;
2442
2443 if (!*args[2]) {
2444 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
2450 err = invalid_char(args[1]);
2451 if (err) {
2452 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2453 file, linenum, *err, args[1]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
Vincent Bernat02779b62016-04-03 13:48:43 +02002458 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2460 err_code |= ERR_ALERT | ERR_ABORT;
2461 goto out;
2462 }
2463
2464 /* the mailers are linked backwards first */
2465 curmailers->count++;
2466 newmailer->next = curmailers->mailer_list;
2467 curmailers->mailer_list = newmailer;
2468 newmailer->mailers = curmailers;
2469 newmailer->conf.file = strdup(file);
2470 newmailer->conf.line = linenum;
2471
2472 newmailer->id = strdup(args[1]);
2473
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002474 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002475 if (!sk) {
2476 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002482 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2483 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002484 file, linenum, args[0], args[1]);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
2489 if (port1 != port2) {
2490 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2491 file, linenum, args[0], args[1], args[2]);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496 if (!port1) {
2497 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2498 file, linenum, args[0], args[1], args[2]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
2503 newmailer->addr = *sk;
2504 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002505 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002506 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002507 }
2508 else if (strcmp(args[0], "timeout") == 0) {
2509 if (!*args[1]) {
2510 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2511 file, linenum, args[0]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515 else if (strcmp(args[1], "mail") == 0) {
2516 const char *res;
2517 unsigned int timeout_mail;
2518 if (!*args[2]) {
2519 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2520 file, linenum, args[0], args[1]);
2521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
2523 }
2524 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2525 if (res) {
2526 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2527 file, linenum, *res, args[0]);
2528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
2531 if (timeout_mail <= 0) {
2532 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
2535 }
2536 curmailers->timeout.mail = timeout_mail;
2537 } else {
2538 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2539 file, linenum, args[0], args[1]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543 }
Simon Horman0d16a402015-01-30 11:22:58 +09002544 else if (*args[0] != 0) {
2545 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
2548 }
2549
2550out:
2551 free(errmsg);
2552 return err_code;
2553}
2554
Simon Horman9dc49962015-01-30 11:22:59 +09002555static void free_email_alert(struct proxy *p)
2556{
2557 free(p->email_alert.mailers.name);
2558 p->email_alert.mailers.name = NULL;
2559 free(p->email_alert.from);
2560 p->email_alert.from = NULL;
2561 free(p->email_alert.to);
2562 p->email_alert.to = NULL;
2563 free(p->email_alert.myhostname);
2564 p->email_alert.myhostname = NULL;
2565}
2566
Willy Tarreau3842f002009-06-14 11:39:52 +02002567int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568{
2569 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002570 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002571 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002572 int rc;
2573 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002574 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002575 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002576 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002577 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002578 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 if (!strcmp(args[0], "listen"))
2581 rc = PR_CAP_LISTEN;
2582 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002583 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002584 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002585 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002586 else
2587 rc = PR_CAP_NONE;
2588
2589 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 if (!*args[1]) {
2591 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002592 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_ABORT;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002597
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002598 err = invalid_char(args[1]);
2599 if (err) {
2600 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2601 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002603 }
2604
Willy Tarreau8f50b682015-05-26 11:45:02 +02002605 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2606 if (curproxy) {
2607 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2608 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2609 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002611 }
2612
Vincent Bernat02779b62016-04-03 13:48:43 +02002613 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_ABORT;
2616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002618
Willy Tarreau97cb7802010-01-03 20:23:58 +01002619 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 curproxy->next = proxy;
2621 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002622 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2623 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002624 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002627 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628
William Lallemand6e62fb62015-04-28 16:55:23 +02002629 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2630 if (curproxy->cap & PR_CAP_FE)
2631 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
2634
2635 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002636 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002637 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002638
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002641 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002642 curproxy->no_options = defproxy.no_options;
2643 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002644 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002645 curproxy->except_net = defproxy.except_net;
2646 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002647 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002648 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002650 if (defproxy.fwdfor_hdr_len) {
2651 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2652 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2653 }
2654
Willy Tarreaub86db342009-11-30 11:50:16 +01002655 if (defproxy.orgto_hdr_len) {
2656 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2657 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2658 }
2659
Mark Lamourinec2247f02012-01-04 13:02:01 -05002660 if (defproxy.server_id_hdr_len) {
2661 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2662 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2663 }
2664
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665 if (curproxy->cap & PR_CAP_FE) {
2666 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002667 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002668 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669
2670 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002671 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2672 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002673
2674 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002678 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002679 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002680 curproxy->fullconn = defproxy.fullconn;
2681 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002682 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002683 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002685 if (defproxy.check_req) {
2686 curproxy->check_req = calloc(1, defproxy.check_len);
2687 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002689 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002691 if (defproxy.expect_str) {
2692 curproxy->expect_str = strdup(defproxy.expect_str);
2693 if (defproxy.expect_regex) {
2694 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002695 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2696 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002697 }
2698 }
2699
Willy Tarreau67402132012-05-31 20:40:20 +02002700 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 if (defproxy.cookie_name)
2702 curproxy->cookie_name = strdup(defproxy.cookie_name);
2703 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002704
2705 if (defproxy.dyncookie_key)
2706 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002707 if (defproxy.cookie_domain)
2708 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002709
Willy Tarreau31936852010-10-06 16:59:56 +02002710 if (defproxy.cookie_maxidle)
2711 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2712
2713 if (defproxy.cookie_maxlife)
2714 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2715
Emeric Brun647caf12009-06-30 17:57:00 +02002716 if (defproxy.rdp_cookie_name)
2717 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2718 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2719
Willy Tarreau01732802007-11-01 22:48:15 +01002720 if (defproxy.url_param_name)
2721 curproxy->url_param_name = strdup(defproxy.url_param_name);
2722 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002723
Benoitaffb4812009-03-25 13:02:10 +01002724 if (defproxy.hh_name)
2725 curproxy->hh_name = strdup(defproxy.hh_name);
2726 curproxy->hh_len = defproxy.hh_len;
2727 curproxy->hh_match_domain = defproxy.hh_match_domain;
2728
Willy Tarreauef9a3602012-12-08 22:29:20 +01002729 if (defproxy.conn_src.iface_name)
2730 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2731 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002732 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002733#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002734 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002735#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002736 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002739 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002740 if (defproxy.capture_name)
2741 curproxy->capture_name = strdup(defproxy.capture_name);
2742 curproxy->capture_namelen = defproxy.capture_namelen;
2743 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745
Willy Tarreau977b8e42006-12-29 14:19:17 +01002746 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002747 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002748 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002749 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002750 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002751 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752 curproxy->mon_net = defproxy.mon_net;
2753 curproxy->mon_mask = defproxy.mon_mask;
2754 if (defproxy.monitor_uri)
2755 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2756 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002757 if (defproxy.defbe.name)
2758 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002759
2760 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002761 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2762 if (curproxy->conf.logformat_string &&
2763 curproxy->conf.logformat_string != default_http_log_format &&
2764 curproxy->conf.logformat_string != default_tcp_log_format &&
2765 curproxy->conf.logformat_string != clf_http_log_format)
2766 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2767
2768 if (defproxy.conf.lfs_file) {
2769 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2770 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2771 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002772
2773 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2774 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2775 if (curproxy->conf.logformat_sd_string &&
2776 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2777 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2778
2779 if (defproxy.conf.lfsd_file) {
2780 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2781 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 }
2784
2785 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002786 curproxy->timeout.connect = defproxy.timeout.connect;
2787 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002788 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002789 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002790 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002791 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002792 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002793 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002794 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002795 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796 }
2797
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002799 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002800
2801 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002802 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002803 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002804 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002805 LIST_INIT(&node->list);
2806 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2807 }
2808
Willy Tarreau62a61232013-04-12 18:13:46 +02002809 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2810 if (curproxy->conf.uniqueid_format_string)
2811 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2812
Dragan Dosen43885c72015-10-01 13:18:13 +02002813 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002814
Willy Tarreau62a61232013-04-12 18:13:46 +02002815 if (defproxy.conf.uif_file) {
2816 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2817 curproxy->conf.uif_line = defproxy.conf.uif_line;
2818 }
William Lallemanda73203e2012-03-12 12:48:57 +01002819
2820 /* copy default header unique id */
2821 if (defproxy.header_unique_id)
2822 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2823
William Lallemand82fe75c2012-10-23 10:25:10 +02002824 /* default compression options */
2825 if (defproxy.comp != NULL) {
2826 curproxy->comp = calloc(1, sizeof(struct comp));
2827 curproxy->comp->algos = defproxy.comp->algos;
2828 curproxy->comp->types = defproxy.comp->types;
2829 }
2830
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002832 curproxy->conf.used_listener_id = EB_ROOT;
2833 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002834
Simon Horman98637e52014-06-20 12:30:16 +09002835 if (defproxy.check_path)
2836 curproxy->check_path = strdup(defproxy.check_path);
2837 if (defproxy.check_command)
2838 curproxy->check_command = strdup(defproxy.check_command);
2839
Simon Horman9dc49962015-01-30 11:22:59 +09002840 if (defproxy.email_alert.mailers.name)
2841 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2842 if (defproxy.email_alert.from)
2843 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2844 if (defproxy.email_alert.to)
2845 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2846 if (defproxy.email_alert.myhostname)
2847 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002848 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002849 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002850
Willy Tarreau93893792009-07-23 13:19:11 +02002851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 }
2853 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2854 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002855 /* FIXME-20070101: we should do this too at the end of the
2856 * config parsing to free all default values.
2857 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002858 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2859 err_code |= ERR_ABORT;
2860 goto out;
2861 }
2862
Willy Tarreaua534fea2008-08-03 12:19:50 +02002863 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002864 free(defproxy.check_command);
2865 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002866 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002867 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002868 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002869 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002870 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002871 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002872 free(defproxy.capture_name);
2873 free(defproxy.monitor_uri);
2874 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002875 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002876 free(defproxy.fwdfor_hdr_name);
2877 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002878 free(defproxy.orgto_hdr_name);
2879 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002880 free(defproxy.server_id_hdr_name);
2881 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002882 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002883 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002884 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002885 free(defproxy.expect_regex);
2886 defproxy.expect_regex = NULL;
2887 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002888
Willy Tarreau62a61232013-04-12 18:13:46 +02002889 if (defproxy.conf.logformat_string != default_http_log_format &&
2890 defproxy.conf.logformat_string != default_tcp_log_format &&
2891 defproxy.conf.logformat_string != clf_http_log_format)
2892 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002893
Willy Tarreau62a61232013-04-12 18:13:46 +02002894 free(defproxy.conf.uniqueid_format_string);
2895 free(defproxy.conf.lfs_file);
2896 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002897 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002898 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002899
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002900 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2901 free(defproxy.conf.logformat_sd_string);
2902 free(defproxy.conf.lfsd_file);
2903
Willy Tarreaua534fea2008-08-03 12:19:50 +02002904 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002905 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002906
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 /* we cannot free uri_auth because it might already be used */
2908 init_default_instance();
2909 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002910 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2911 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915 else if (curproxy == NULL) {
2916 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002920
2921 /* update the current file and line being parsed */
2922 curproxy->conf.args.file = curproxy->conf.file;
2923 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002924
2925 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002926 if (!strcmp(args[0], "server") ||
2927 !strcmp(args[0], "default-server") ||
2928 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002929 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2930 if (err_code & ERR_FATAL)
2931 goto out;
2932 }
2933 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002934 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002935 int cur_arg;
2936
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 if (curproxy == &defproxy) {
2938 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002942 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944
Willy Tarreau24709282013-03-10 21:32:12 +01002945 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002946 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002951
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002952 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002953
2954 /* use default settings for unix sockets */
2955 bind_conf->ux.uid = global.unix_bind.ux.uid;
2956 bind_conf->ux.gid = global.unix_bind.ux.gid;
2957 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002958
2959 /* NOTE: the following line might create several listeners if there
2960 * are comma-separated IPs or port ranges. So all further processing
2961 * will have to be applied to all listeners created after last_listen.
2962 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002963 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2964 if (errmsg && *errmsg) {
2965 indent_msg(&errmsg, 2);
2966 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002967 }
2968 else
2969 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2970 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002974
Willy Tarreau4348fad2012-09-20 16:48:07 +02002975 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2976 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002977 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002978 }
2979
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002980 cur_arg = 2;
2981 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002982 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002983 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002984 char *err;
2985
Willy Tarreau26982662012-09-12 23:17:10 +02002986 kw = bind_find_kw(args[cur_arg]);
2987 if (kw) {
2988 char *err = NULL;
2989 int code;
2990
2991 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002992 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2993 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002994 cur_arg += 1 + kw->skip ;
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998
Willy Tarreau4348fad2012-09-20 16:48:07 +02002999 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003000 err_code |= code;
3001
3002 if (code) {
3003 if (err && *err) {
3004 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003005 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003006 }
3007 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003008 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3009 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003010 if (code & ERR_FATAL) {
3011 free(err);
3012 cur_arg += 1 + kw->skip;
3013 goto out;
3014 }
3015 }
3016 free(err);
3017 cur_arg += 1 + kw->skip;
3018 continue;
3019 }
3020
Willy Tarreau8638f482012-09-18 18:01:17 +02003021 err = NULL;
3022 if (!bind_dumped) {
3023 bind_dump_kws(&err);
3024 indent_msg(&err, 4);
3025 bind_dumped = 1;
3026 }
3027
3028 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3029 file, linenum, args[0], args[1], args[cur_arg],
3030 err ? " Registered keywords :" : "", err ? err : "");
3031 free(err);
3032
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003035 }
Willy Tarreau93893792009-07-23 13:19:11 +02003036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 }
3038 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003039 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3041 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003045 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 /* flush useless bits */
3049 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003052 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003053 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055
William Lallemanddf1425a2015-04-28 20:17:49 +02003056 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3057 goto out;
3058
Willy Tarreau1c47f852006-07-09 08:22:27 +02003059 if (!*args[1]) {
3060 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003064 }
3065
Willy Tarreaua534fea2008-08-03 12:19:50 +02003066 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003067 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003068 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003069 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003070 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3071
Willy Tarreau93893792009-07-23 13:19:11 +02003072 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003075 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3076 goto out;
3077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3079 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3080 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3081 else {
3082 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
3086 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003087 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003088 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003089
3090 if (curproxy == &defproxy) {
3091 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003095 }
3096
William Lallemanddf1425a2015-04-28 20:17:49 +02003097 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3098 goto out;
3099
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003100 if (!*args[1]) {
3101 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003105 }
3106
3107 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003108 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003109 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003110
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003111 if (curproxy->uuid <= 0) {
3112 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003113 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003116 }
3117
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003118 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3119 if (node) {
3120 struct proxy *target = container_of(node, struct proxy, conf.id);
3121 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3122 file, linenum, proxy_type_str(curproxy), curproxy->id,
3123 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003128 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003129 else if (!strcmp(args[0], "description")) {
3130 int i, len=0;
3131 char *d;
3132
Cyril Bonté99ed3272010-01-24 23:29:44 +01003133 if (curproxy == &defproxy) {
3134 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3135 file, linenum, args[0]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003140 if (!*args[1]) {
3141 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3142 file, linenum, args[0]);
3143 return -1;
3144 }
3145
Willy Tarreau348acfe2014-04-14 15:00:39 +02003146 for (i = 1; *args[i]; i++)
3147 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003148
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003149 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003150 curproxy->desc = d;
3151
Willy Tarreau348acfe2014-04-14 15:00:39 +02003152 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3153 for (i = 2; *args[i]; i++)
3154 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003155
3156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003158 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 curproxy->state = PR_STSTOPPED;
3161 }
3162 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003163 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 curproxy->state = PR_STNEW;
3166 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003167 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3168 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003169 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003170
3171 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003172 unsigned int low, high;
3173
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003174 if (strcmp(args[cur_arg], "all") == 0) {
3175 set = 0;
3176 break;
3177 }
3178 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003179 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003180 }
3181 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003182 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003183 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003184 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003185 char *dash = strchr(args[cur_arg], '-');
3186
3187 low = high = str2uic(args[cur_arg]);
3188 if (dash)
3189 high = str2uic(dash + 1);
3190
3191 if (high < low) {
3192 unsigned int swap = low;
3193 low = high;
3194 high = swap;
3195 }
3196
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003197 if (low < 1 || high > LONGBITS) {
3198 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3199 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003202 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003203 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003204 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003205 }
3206 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003207 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3208 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003211 }
3212 cur_arg++;
3213 }
3214 curproxy->bind_proc = set;
3215 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003216 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003217 if (curproxy == &defproxy) {
3218 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003221 }
3222
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003223 err = invalid_char(args[1]);
3224 if (err) {
3225 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3226 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003228 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003229 }
3230
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003231 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003232 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3233 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003236 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003237 }
3238 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3239
3240 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3241 err_code |= ERR_WARN;
3242
3243 if (*(args[1]) == 0) {
3244 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3245 file, linenum, args[0]);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249 free(curproxy->dyncookie_key);
3250 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3253 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254
Willy Tarreau977b8e42006-12-29 14:19:17 +01003255 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003257
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 if (*(args[1]) == 0) {
3259 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003264
Willy Tarreau67402132012-05-31 20:40:20 +02003265 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003266 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003267 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003268 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 curproxy->cookie_name = strdup(args[1]);
3270 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003271
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 cur_arg = 2;
3273 while (*(args[cur_arg])) {
3274 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003275 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003278 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
3280 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003281 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003284 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
3286 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003287 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003289 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003290 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003293 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003295 else if (!strcmp(args[cur_arg], "httponly")) {
3296 curproxy->ck_opts |= PR_CK_HTTPONLY;
3297 }
3298 else if (!strcmp(args[cur_arg], "secure")) {
3299 curproxy->ck_opts |= PR_CK_SECURE;
3300 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003301 else if (!strcmp(args[cur_arg], "domain")) {
3302 if (!*args[cur_arg + 1]) {
3303 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3304 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003307 }
3308
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003309 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003310 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003311 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3312 " dots nor does not start with a dot."
3313 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003314 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003315 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003316 }
3317
3318 err = invalid_domainchar(args[cur_arg + 1]);
3319 if (err) {
3320 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3321 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003324 }
3325
Willy Tarreau68a897b2009-12-03 23:28:34 +01003326 if (!curproxy->cookie_domain) {
3327 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3328 } else {
3329 /* one domain was already specified, add another one by
3330 * building the string which will be returned along with
3331 * the cookie.
3332 */
3333 char *new_ptr;
3334 int new_len = strlen(curproxy->cookie_domain) +
3335 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3336 new_ptr = malloc(new_len);
3337 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3338 free(curproxy->cookie_domain);
3339 curproxy->cookie_domain = new_ptr;
3340 }
Willy Tarreau31936852010-10-06 16:59:56 +02003341 cur_arg++;
3342 }
3343 else if (!strcmp(args[cur_arg], "maxidle")) {
3344 unsigned int maxidle;
3345 const char *res;
3346
3347 if (!*args[cur_arg + 1]) {
3348 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3349 file, linenum, args[cur_arg]);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353
3354 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3355 if (res) {
3356 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3357 file, linenum, *res, args[cur_arg]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361 curproxy->cookie_maxidle = maxidle;
3362 cur_arg++;
3363 }
3364 else if (!strcmp(args[cur_arg], "maxlife")) {
3365 unsigned int maxlife;
3366 const char *res;
3367
3368 if (!*args[cur_arg + 1]) {
3369 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3370 file, linenum, args[cur_arg]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374
3375 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3376 if (res) {
3377 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3378 file, linenum, *res, args[cur_arg]);
3379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
3381 }
3382 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003383 cur_arg++;
3384 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003385 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003386
3387 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3388 err_code |= ERR_WARN;
3389 curproxy->ck_opts |= PR_CK_DYNAMIC;
3390 }
3391
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003393 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
3398 cur_arg++;
3399 }
Willy Tarreau67402132012-05-31 20:40:20 +02003400 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3402 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 }
3405
Willy Tarreau67402132012-05-31 20:40:20 +02003406 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3408 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003411
Willy Tarreau67402132012-05-31 20:40:20 +02003412 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003413 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3414 file, linenum);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003418 else if (!strcmp(args[0], "email-alert")) {
3419 if (*(args[1]) == 0) {
3420 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3421 file, linenum, args[0]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425
3426 if (!strcmp(args[1], "from")) {
3427 if (*(args[1]) == 0) {
3428 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3429 file, linenum, args[1]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433 free(curproxy->email_alert.from);
3434 curproxy->email_alert.from = strdup(args[2]);
3435 }
3436 else if (!strcmp(args[1], "mailers")) {
3437 if (*(args[1]) == 0) {
3438 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3439 file, linenum, args[1]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443 free(curproxy->email_alert.mailers.name);
3444 curproxy->email_alert.mailers.name = strdup(args[2]);
3445 }
3446 else if (!strcmp(args[1], "myhostname")) {
3447 if (*(args[1]) == 0) {
3448 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3449 file, linenum, args[1]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 free(curproxy->email_alert.myhostname);
3454 curproxy->email_alert.myhostname = strdup(args[2]);
3455 }
Simon Horman64e34162015-02-06 11:11:57 +09003456 else if (!strcmp(args[1], "level")) {
3457 curproxy->email_alert.level = get_log_level(args[2]);
3458 if (curproxy->email_alert.level < 0) {
3459 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3460 file, linenum, args[1], args[2]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464 }
Simon Horman9dc49962015-01-30 11:22:59 +09003465 else if (!strcmp(args[1], "to")) {
3466 if (*(args[1]) == 0) {
3467 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3468 file, linenum, args[1]);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
3472 free(curproxy->email_alert.to);
3473 curproxy->email_alert.to = strdup(args[2]);
3474 }
3475 else {
3476 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3477 file, linenum, args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
Simon Horman64e34162015-02-06 11:11:57 +09003481 /* Indicate that the email_alert is at least partially configured */
3482 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003483 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003484 else if (!strcmp(args[0], "external-check")) {
3485 if (*(args[1]) == 0) {
3486 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3487 file, linenum, args[0]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491
3492 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003493 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003494 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003495 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003496 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3497 file, linenum, args[1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501 free(curproxy->check_command);
3502 curproxy->check_command = strdup(args[2]);
3503 }
3504 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003505 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003506 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003507 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003508 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3509 file, linenum, args[1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513 free(curproxy->check_path);
3514 curproxy->check_path = strdup(args[2]);
3515 }
3516 else {
3517 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3518 file, linenum, args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003523 else if (!strcmp(args[0], "persist")) { /* persist */
3524 if (*(args[1]) == 0) {
3525 Alert("parsing [%s:%d] : missing persist method.\n",
3526 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003529 }
3530
3531 if (!strncmp(args[1], "rdp-cookie", 10)) {
3532 curproxy->options2 |= PR_O2_RDPC_PRST;
3533
Emeric Brunb982a3d2010-01-04 15:45:53 +01003534 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003535 const char *beg, *end;
3536
3537 beg = args[1] + 11;
3538 end = strchr(beg, ')');
3539
William Lallemanddf1425a2015-04-28 20:17:49 +02003540 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3541 goto out;
3542
Emeric Brun647caf12009-06-30 17:57:00 +02003543 if (!end || end == beg) {
3544 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003548 }
3549
3550 free(curproxy->rdp_cookie_name);
3551 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3552 curproxy->rdp_cookie_len = end-beg;
3553 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003554 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003555 free(curproxy->rdp_cookie_name);
3556 curproxy->rdp_cookie_name = strdup("msts");
3557 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3558 }
3559 else { /* syntax */
3560 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3561 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003564 }
3565 }
3566 else {
3567 Alert("parsing [%s:%d] : unknown persist method.\n",
3568 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003571 }
3572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003574 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003578 else if (!strcmp(args[0], "load-server-state-from-file")) {
3579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3580 err_code |= ERR_WARN;
3581 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3582 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3583 }
3584 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3585 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3586 }
3587 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3588 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3589 }
3590 else {
3591 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3592 file, linenum, args[0], args[1]);
3593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
3595 }
3596 }
3597 else if (!strcmp(args[0], "server-state-file-name")) {
3598 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3599 err_code |= ERR_WARN;
3600 if (*(args[1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3602 file, linenum, args[0]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606 else if (!strcmp(args[1], "use-backend-name"))
3607 curproxy->server_state_file_name = strdup(curproxy->id);
3608 else
3609 curproxy->server_state_file_name = strdup(args[1]);
3610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003612 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003614
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003616 if (curproxy == &defproxy) {
3617 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
3621
William Lallemand1a748ae2015-05-19 16:37:23 +02003622 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3623 goto out;
3624
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 if (*(args[4]) == 0) {
3626 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003631 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 curproxy->capture_name = strdup(args[2]);
3633 curproxy->capture_namelen = strlen(curproxy->capture_name);
3634 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 curproxy->to_log |= LW_COOKIE;
3636 }
3637 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3638 struct cap_hdr *hdr;
3639
3640 if (curproxy == &defproxy) {
3641 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 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645
William Lallemand1a748ae2015-05-19 16:37:23 +02003646 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3647 goto out;
3648
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3650 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3651 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
3655
Vincent Bernat02779b62016-04-03 13:48:43 +02003656 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 hdr->next = curproxy->req_cap;
3658 hdr->name = strdup(args[3]);
3659 hdr->namelen = strlen(args[3]);
3660 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003661 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 hdr->index = curproxy->nb_req_cap++;
3663 curproxy->req_cap = hdr;
3664 curproxy->to_log |= LW_REQHDR;
3665 }
3666 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3667 struct cap_hdr *hdr;
3668
3669 if (curproxy == &defproxy) {
3670 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 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 }
3674
William Lallemand1a748ae2015-05-19 16:37:23 +02003675 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3676 goto out;
3677
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3679 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3680 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003684 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 hdr->next = curproxy->rsp_cap;
3686 hdr->name = strdup(args[3]);
3687 hdr->namelen = strlen(args[3]);
3688 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003689 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 hdr->index = curproxy->nb_rsp_cap++;
3691 curproxy->rsp_cap = hdr;
3692 curproxy->to_log |= LW_RSPHDR;
3693 }
3694 else {
3695 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 }
3700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003702 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003704
William Lallemanddf1425a2015-04-28 20:17:49 +02003705 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3706 goto out;
3707
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 if (*(args[1]) == 0) {
3709 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 }
3714 curproxy->conn_retries = atol(args[1]);
3715 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003716 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003717 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003718
3719 if (curproxy == &defproxy) {
3720 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724
Willy Tarreau20b0de52012-12-24 15:45:22 +01003725 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003726 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003727 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3728 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3729 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3730 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003731 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 +01003732 file, linenum, args[0]);
3733 err_code |= ERR_WARN;
3734 }
3735
Willy Tarreauff011f22011-01-06 17:51:27 +01003736 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003737
Willy Tarreauff011f22011-01-06 17:51:27 +01003738 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003739 err_code |= ERR_ALERT | ERR_ABORT;
3740 goto out;
3741 }
3742
Willy Tarreau5002f572014-04-23 01:32:02 +02003743 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003744 err_code |= warnif_cond_conflicts(rule->cond,
3745 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3746 file, linenum);
3747
Willy Tarreauff011f22011-01-06 17:51:27 +01003748 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003749 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003750 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003751 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003752
3753 if (curproxy == &defproxy) {
3754 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758
3759 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003760 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003761 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3762 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003763 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3764 file, linenum, args[0]);
3765 err_code |= ERR_WARN;
3766 }
3767
3768 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3769
3770 if (!rule) {
3771 err_code |= ERR_ALERT | ERR_ABORT;
3772 goto out;
3773 }
3774
3775 err_code |= warnif_cond_conflicts(rule->cond,
3776 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3777 file, linenum);
3778
3779 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3780 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003781 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3782 /* set the header name and length into the proxy structure */
3783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3784 err_code |= ERR_WARN;
3785
3786 if (!*args[1]) {
3787 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3788 file, linenum, args[0]);
3789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
3791 }
3792
3793 /* set the desired header name */
3794 free(curproxy->server_id_hdr_name);
3795 curproxy->server_id_hdr_name = strdup(args[1]);
3796 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3797 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003798 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003799 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003800
Willy Tarreaub099aca2008-10-12 17:26:37 +02003801 if (curproxy == &defproxy) {
3802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003805 }
3806
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003807 /* emulate "block" using "http-request block". Since these rules are supposed to
3808 * be processed before all http-request rules, we put them into their own list
3809 * and will insert them at the end.
3810 */
3811 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3812 if (!rule) {
3813 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003814 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003815 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003816 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3817 err_code |= warnif_cond_conflicts(rule->cond,
3818 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3819 file, linenum);
3820 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003821
3822 if (!already_warned(WARN_BLOCK_DEPRECATED))
3823 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]);
3824
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003825 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003826 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003827 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003828
Cyril Bonté99ed3272010-01-24 23:29:44 +01003829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834
Willy Tarreaube4653b2015-05-28 15:26:58 +02003835 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003836 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3837 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003840 }
3841
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003842 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003843 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003844 err_code |= warnif_cond_conflicts(rule->cond,
3845 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3846 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003847 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003848 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003849 struct switching_rule *rule;
3850
Willy Tarreaub099aca2008-10-12 17:26:37 +02003851 if (curproxy == &defproxy) {
3852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003855 }
3856
Willy Tarreau55ea7572007-06-17 19:56:27 +02003857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003859
3860 if (*(args[1]) == 0) {
3861 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003864 }
3865
Willy Tarreauf51658d2014-04-23 01:21:56 +02003866 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3867 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3868 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3869 file, linenum, errmsg);
3870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003873
Willy Tarreauf51658d2014-04-23 01:21:56 +02003874 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003875 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003876 else if (*args[2]) {
3877 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3878 file, linenum, args[2]);
3879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003882
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003883 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003884 if (!rule) {
3885 Alert("Out of memory error.\n");
3886 goto out;
3887 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003888 rule->cond = cond;
3889 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003890 rule->line = linenum;
3891 rule->file = strdup(file);
3892 if (!rule->file) {
3893 Alert("Out of memory error.\n");
3894 goto out;
3895 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003896 LIST_INIT(&rule->list);
3897 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3898 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003899 else if (strcmp(args[0], "use-server") == 0) {
3900 struct server_rule *rule;
3901
3902 if (curproxy == &defproxy) {
3903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907
3908 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3909 err_code |= ERR_WARN;
3910
3911 if (*(args[1]) == 0) {
3912 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916
3917 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3918 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3919 file, linenum, args[0]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003924 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3925 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3926 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003931 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003932
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003933 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003934 rule->cond = cond;
3935 rule->srv.name = strdup(args[1]);
3936 LIST_INIT(&rule->list);
3937 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3938 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3939 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003940 else if ((!strcmp(args[0], "force-persist")) ||
3941 (!strcmp(args[0], "ignore-persist"))) {
3942 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003943
3944 if (curproxy == &defproxy) {
3945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949
3950 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3951 err_code |= ERR_WARN;
3952
Willy Tarreauef6494c2010-01-28 17:12:36 +01003953 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003954 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3955 file, linenum, args[0]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003960 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3961 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3962 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
3965 }
3966
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003967 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3968 * where force-persist is applied.
3969 */
3970 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003971
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003972 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003973 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003974 if (!strcmp(args[0], "force-persist")) {
3975 rule->type = PERSIST_TYPE_FORCE;
3976 } else {
3977 rule->type = PERSIST_TYPE_IGNORE;
3978 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003979 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003980 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003981 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982 else if (!strcmp(args[0], "stick-table")) {
3983 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003984 struct proxy *other;
3985
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003986 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003987 if (other) {
3988 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3989 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003993
Emeric Brun32da3c42010-09-23 18:39:19 +02003994 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003995 curproxy->table.type = (unsigned int)-1;
3996 while (*args[myidx]) {
3997 const char *err;
3998
3999 if (strcmp(args[myidx], "size") == 0) {
4000 myidx++;
4001 if (!*(args[myidx])) {
4002 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4003 file, linenum, args[myidx-1]);
4004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
4006 }
4007 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4008 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4009 file, linenum, *err, args[myidx-1]);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004013 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004014 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004015 else if (strcmp(args[myidx], "peers") == 0) {
4016 myidx++;
Godbach50523162013-12-11 19:48:57 +08004017 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004018 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4019 file, linenum, args[myidx-1]);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Godbach50523162013-12-11 19:48:57 +08004022 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004023 curproxy->table.peers.name = strdup(args[myidx++]);
4024 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004025 else if (strcmp(args[myidx], "expire") == 0) {
4026 myidx++;
4027 if (!*(args[myidx])) {
4028 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4029 file, linenum, args[myidx-1]);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4034 if (err) {
4035 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4036 file, linenum, *err, args[myidx-1]);
4037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
4039 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004040 if (val > INT_MAX) {
4041 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4042 file, linenum, val);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004046 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004047 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004048 }
4049 else if (strcmp(args[myidx], "nopurge") == 0) {
4050 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004051 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004052 }
4053 else if (strcmp(args[myidx], "type") == 0) {
4054 myidx++;
4055 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4056 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4057 file, linenum, args[myidx]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004061 /* myidx already points to next arg */
4062 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004063 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004064 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004065 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004066
4067 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004068 nw = args[myidx];
4069 while (*nw) {
4070 /* the "store" keyword supports a comma-separated list */
4071 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004072 sa = NULL; /* store arg */
4073 while (*nw && *nw != ',') {
4074 if (*nw == '(') {
4075 *nw = 0;
4076 sa = ++nw;
4077 while (*nw != ')') {
4078 if (!*nw) {
4079 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4080 file, linenum, args[0], cw);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 nw++;
4085 }
4086 *nw = '\0';
4087 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004088 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004089 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004090 if (*nw)
4091 *nw++ = '\0';
4092 type = stktable_get_data_type(cw);
4093 if (type < 0) {
4094 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4095 file, linenum, args[0], cw);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
Willy Tarreauac782882010-06-20 10:41:54 +02004099
4100 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4101 switch (err) {
4102 case PE_NONE: break;
4103 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004104 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4105 file, linenum, args[0], cw);
4106 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004107 break;
4108
4109 case PE_ARG_MISSING:
4110 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4111 file, linenum, args[0], cw);
4112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
4114
4115 case PE_ARG_NOT_USED:
4116 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4117 file, linenum, args[0], cw);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120
4121 default:
4122 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4123 file, linenum, args[0], cw);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004126 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004127 }
4128 myidx++;
4129 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004130 else {
4131 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4132 file, linenum, args[myidx]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004136 }
4137
4138 if (!curproxy->table.size) {
4139 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4140 file, linenum);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
4143 }
4144
4145 if (curproxy->table.type == (unsigned int)-1) {
4146 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4147 file, linenum);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151 }
4152 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004153 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004154 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004155 int myidx = 0;
4156 const char *name = NULL;
4157 int flags;
4158
4159 if (curproxy == &defproxy) {
4160 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164
4165 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4166 err_code |= ERR_WARN;
4167 goto out;
4168 }
4169
4170 myidx++;
4171 if ((strcmp(args[myidx], "store") == 0) ||
4172 (strcmp(args[myidx], "store-request") == 0)) {
4173 myidx++;
4174 flags = STK_IS_STORE;
4175 }
4176 else if (strcmp(args[myidx], "store-response") == 0) {
4177 myidx++;
4178 flags = STK_IS_STORE | STK_ON_RSP;
4179 }
4180 else if (strcmp(args[myidx], "match") == 0) {
4181 myidx++;
4182 flags = STK_IS_MATCH;
4183 }
4184 else if (strcmp(args[myidx], "on") == 0) {
4185 myidx++;
4186 flags = STK_IS_MATCH | STK_IS_STORE;
4187 }
4188 else {
4189 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192 }
4193
4194 if (*(args[myidx]) == 0) {
4195 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198 }
4199
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004200 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004201 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004202 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004203 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
4206 }
4207
4208 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004209 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4210 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4211 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004212 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004213 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 goto out;
4215 }
4216 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004217 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4218 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4219 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004220 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004221 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004222 goto out;
4223 }
4224 }
4225
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004226 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004227 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004228
Emeric Brunb982a3d2010-01-04 15:45:53 +01004229 if (strcmp(args[myidx], "table") == 0) {
4230 myidx++;
4231 name = args[myidx++];
4232 }
4233
Willy Tarreauef6494c2010-01-28 17:12:36 +01004234 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004235 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4236 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4237 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004238 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004239 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004240 goto out;
4241 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004242 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004243 else if (*(args[myidx])) {
4244 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4245 file, linenum, args[0], args[myidx]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004247 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004248 goto out;
4249 }
Emeric Brun97679e72010-09-23 17:56:44 +02004250 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004251 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004252 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004253 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004254
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004255 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004256 rule->cond = cond;
4257 rule->expr = expr;
4258 rule->flags = flags;
4259 rule->table.name = name ? strdup(name) : NULL;
4260 LIST_INIT(&rule->list);
4261 if (flags & STK_ON_RSP)
4262 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4263 else
4264 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 else if (!strcmp(args[0], "stats")) {
4267 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4268 curproxy->uri_auth = NULL; /* we must detach from the default config */
4269
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004270 if (!*args[1]) {
4271 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004272 } else if (!strcmp(args[1], "admin")) {
4273 struct stats_admin_rule *rule;
4274
4275 if (curproxy == &defproxy) {
4276 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280
4281 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4282 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4283 err_code |= ERR_ALERT | ERR_ABORT;
4284 goto out;
4285 }
4286
4287 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4288 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4289 file, linenum, args[0], args[1]);
4290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
4292 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004293 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4294 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4295 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004300 err_code |= warnif_cond_conflicts(cond,
4301 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4302 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004303
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004304 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004305 rule->cond = cond;
4306 LIST_INIT(&rule->list);
4307 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 } else if (!strcmp(args[1], "uri")) {
4309 if (*(args[2]) == 0) {
4310 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_ABORT;
4316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 }
4318 } else if (!strcmp(args[1], "realm")) {
4319 if (*(args[2]) == 0) {
4320 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_ABORT;
4326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004328 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004329 unsigned interval;
4330
4331 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4332 if (err) {
4333 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4334 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004337 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4338 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_ABORT;
4340 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004341 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004342 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004343 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004344
4345 if (curproxy == &defproxy) {
4346 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
4349 }
4350
4351 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4353 err_code |= ERR_ALERT | ERR_ABORT;
4354 goto out;
4355 }
4356
Willy Tarreauff011f22011-01-06 17:51:27 +01004357 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004358 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004359 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4360 file, linenum, args[0]);
4361 err_code |= ERR_WARN;
4362 }
4363
Willy Tarreauff011f22011-01-06 17:51:27 +01004364 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004365
Willy Tarreauff011f22011-01-06 17:51:27 +01004366 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004367 err_code |= ERR_ALERT | ERR_ABORT;
4368 goto out;
4369 }
4370
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004371 err_code |= warnif_cond_conflicts(rule->cond,
4372 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4373 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004374 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004375
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 } else if (!strcmp(args[1], "auth")) {
4377 if (*(args[2]) == 0) {
4378 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4382 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_ABORT;
4384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 }
4386 } else if (!strcmp(args[1], "scope")) {
4387 if (*(args[2]) == 0) {
4388 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4392 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_ABORT;
4394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 }
4396 } else if (!strcmp(args[1], "enable")) {
4397 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4398 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_ABORT;
4400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004402 } else if (!strcmp(args[1], "hide-version")) {
4403 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4404 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_ABORT;
4406 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004407 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004408 } else if (!strcmp(args[1], "show-legends")) {
4409 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4410 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4411 err_code |= ERR_ALERT | ERR_ABORT;
4412 goto out;
4413 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004414 } else if (!strcmp(args[1], "show-node")) {
4415
4416 if (*args[2]) {
4417 int i;
4418 char c;
4419
4420 for (i=0; args[2][i]; i++) {
4421 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004422 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4423 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004424 break;
4425 }
4426
4427 if (!i || args[2][i]) {
4428 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4429 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4430 file, linenum, args[0], args[1]);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
4434 }
4435
4436 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4437 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4438 err_code |= ERR_ALERT | ERR_ABORT;
4439 goto out;
4440 }
4441 } else if (!strcmp(args[1], "show-desc")) {
4442 char *desc = NULL;
4443
4444 if (*args[2]) {
4445 int i, len=0;
4446 char *d;
4447
Willy Tarreau348acfe2014-04-14 15:00:39 +02004448 for (i = 2; *args[i]; i++)
4449 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004450
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004451 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004452
Willy Tarreau348acfe2014-04-14 15:00:39 +02004453 d += snprintf(d, desc + len - d, "%s", args[2]);
4454 for (i = 3; *args[i]; i++)
4455 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004456 }
4457
4458 if (!*args[2] && !global.desc)
4459 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4460 file, linenum, args[1]);
4461 else {
4462 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4463 free(desc);
4464 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4465 err_code |= ERR_ALERT | ERR_ABORT;
4466 goto out;
4467 }
4468 free(desc);
4469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004471stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004472 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 +01004473 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 }
4477 }
4478 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004479 int optnum;
4480
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004481 if (*(args[1]) == '\0') {
4482 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4483 file, linenum, args[0]);
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 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004487
4488 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4489 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004490 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4491 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4492 file, linenum, cfg_opts[optnum].name);
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004496 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4497 goto out;
4498
Willy Tarreau93893792009-07-23 13:19:11 +02004499 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4500 err_code |= ERR_WARN;
4501 goto out;
4502 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004503
Willy Tarreau3842f002009-06-14 11:39:52 +02004504 curproxy->no_options &= ~cfg_opts[optnum].val;
4505 curproxy->options &= ~cfg_opts[optnum].val;
4506
4507 switch (kwm) {
4508 case KWM_STD:
4509 curproxy->options |= cfg_opts[optnum].val;
4510 break;
4511 case KWM_NO:
4512 curproxy->no_options |= cfg_opts[optnum].val;
4513 break;
4514 case KWM_DEF: /* already cleared */
4515 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004516 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004517
Willy Tarreau93893792009-07-23 13:19:11 +02004518 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004519 }
4520 }
4521
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004522 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4523 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004524 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4525 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4526 file, linenum, cfg_opts2[optnum].name);
4527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004530 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4531 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004532 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4533 err_code |= ERR_WARN;
4534 goto out;
4535 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004536
Willy Tarreau3842f002009-06-14 11:39:52 +02004537 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4538 curproxy->options2 &= ~cfg_opts2[optnum].val;
4539
4540 switch (kwm) {
4541 case KWM_STD:
4542 curproxy->options2 |= cfg_opts2[optnum].val;
4543 break;
4544 case KWM_NO:
4545 curproxy->no_options2 |= cfg_opts2[optnum].val;
4546 break;
4547 case KWM_DEF: /* already cleared */
4548 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004549 }
Willy Tarreau93893792009-07-23 13:19:11 +02004550 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004551 }
4552 }
4553
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004554 /* HTTP options override each other. They can be cancelled using
4555 * "no option xxx" which only switches to default mode if the mode
4556 * was this one (useful for cancelling options set in defaults
4557 * sections).
4558 */
4559 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004560 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4561 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004562 if (kwm == KWM_STD) {
4563 curproxy->options &= ~PR_O_HTTP_MODE;
4564 curproxy->options |= PR_O_HTTP_PCL;
4565 goto out;
4566 }
4567 else if (kwm == KWM_NO) {
4568 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4569 curproxy->options &= ~PR_O_HTTP_MODE;
4570 goto out;
4571 }
4572 }
4573 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004574 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4575 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004576 if (kwm == KWM_STD) {
4577 curproxy->options &= ~PR_O_HTTP_MODE;
4578 curproxy->options |= PR_O_HTTP_FCL;
4579 goto out;
4580 }
4581 else if (kwm == KWM_NO) {
4582 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4583 curproxy->options &= ~PR_O_HTTP_MODE;
4584 goto out;
4585 }
4586 }
4587 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004588 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4589 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004590 if (kwm == KWM_STD) {
4591 curproxy->options &= ~PR_O_HTTP_MODE;
4592 curproxy->options |= PR_O_HTTP_SCL;
4593 goto out;
4594 }
4595 else if (kwm == KWM_NO) {
4596 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4597 curproxy->options &= ~PR_O_HTTP_MODE;
4598 goto out;
4599 }
4600 }
4601 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004602 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4603 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004604 if (kwm == KWM_STD) {
4605 curproxy->options &= ~PR_O_HTTP_MODE;
4606 curproxy->options |= PR_O_HTTP_KAL;
4607 goto out;
4608 }
4609 else if (kwm == KWM_NO) {
4610 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4611 curproxy->options &= ~PR_O_HTTP_MODE;
4612 goto out;
4613 }
4614 }
4615 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004616 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4617 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004618 if (kwm == KWM_STD) {
4619 curproxy->options &= ~PR_O_HTTP_MODE;
4620 curproxy->options |= PR_O_HTTP_TUN;
4621 goto out;
4622 }
4623 else if (kwm == KWM_NO) {
4624 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4625 curproxy->options &= ~PR_O_HTTP_MODE;
4626 goto out;
4627 }
4628 }
4629
Joseph Lynch726ab712015-05-11 23:25:34 -07004630 /* Redispatch can take an integer argument that control when the
4631 * resispatch occurs. All values are relative to the retries option.
4632 * This can be cancelled using "no option xxx".
4633 */
4634 if (strcmp(args[1], "redispatch") == 0) {
4635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4636 err_code |= ERR_WARN;
4637 goto out;
4638 }
4639
4640 curproxy->no_options &= ~PR_O_REDISP;
4641 curproxy->options &= ~PR_O_REDISP;
4642
4643 switch (kwm) {
4644 case KWM_STD:
4645 curproxy->options |= PR_O_REDISP;
4646 curproxy->redispatch_after = -1;
4647 if(*args[2]) {
4648 curproxy->redispatch_after = atol(args[2]);
4649 }
4650 break;
4651 case KWM_NO:
4652 curproxy->no_options |= PR_O_REDISP;
4653 curproxy->redispatch_after = 0;
4654 break;
4655 case KWM_DEF: /* already cleared */
4656 break;
4657 }
4658 goto out;
4659 }
4660
Willy Tarreau3842f002009-06-14 11:39:52 +02004661 if (kwm != KWM_STD) {
4662 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004663 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004666 }
4667
Emeric Brun3a058f32009-06-30 18:26:00 +02004668 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004669 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004671 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004672 if (*(args[2]) != '\0') {
4673 if (!strcmp(args[2], "clf")) {
4674 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004675 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004676 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004677 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004680 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004681 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4682 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004683 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004684 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4685 char *oldlogformat = "log-format";
4686 char *clflogformat = "";
4687
4688 if (curproxy->conf.logformat_string == default_http_log_format)
4689 oldlogformat = "option httplog";
4690 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4691 oldlogformat = "option tcplog";
4692 else if (curproxy->conf.logformat_string == clf_http_log_format)
4693 oldlogformat = "option httplog clf";
4694 if (logformat == clf_http_log_format)
4695 clflogformat = " clf";
4696 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4697 file, linenum, clflogformat, oldlogformat);
4698 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004699 if (curproxy->conf.logformat_string != default_http_log_format &&
4700 curproxy->conf.logformat_string != default_tcp_log_format &&
4701 curproxy->conf.logformat_string != clf_http_log_format)
4702 free(curproxy->conf.logformat_string);
4703 curproxy->conf.logformat_string = logformat;
4704
4705 free(curproxy->conf.lfs_file);
4706 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4707 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004708 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004709 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004710 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4711 char *oldlogformat = "log-format";
4712
4713 if (curproxy->conf.logformat_string == default_http_log_format)
4714 oldlogformat = "option httplog";
4715 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4716 oldlogformat = "option tcplog";
4717 else if (curproxy->conf.logformat_string == clf_http_log_format)
4718 oldlogformat = "option httplog clf";
4719 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4720 file, linenum, oldlogformat);
4721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004723 if (curproxy->conf.logformat_string != default_http_log_format &&
4724 curproxy->conf.logformat_string != default_tcp_log_format &&
4725 curproxy->conf.logformat_string != clf_http_log_format)
4726 free(curproxy->conf.logformat_string);
4727 curproxy->conf.logformat_string = default_tcp_log_format;
4728
4729 free(curproxy->conf.lfs_file);
4730 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4731 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004732
4733 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4734 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004737 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004738 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004740
William Lallemanddf1425a2015-04-28 20:17:49 +02004741 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4742 goto out;
4743
Willy Tarreau13943ab2006-12-31 00:24:10 +01004744 if (curproxy->cap & PR_CAP_FE)
4745 curproxy->options |= PR_O_TCP_CLI_KA;
4746 if (curproxy->cap & PR_CAP_BE)
4747 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
4749 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004751 err_code |= ERR_WARN;
4752
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004754 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004755 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004756 curproxy->options2 &= ~PR_O2_CHK_ANY;
4757 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 if (!*args[2]) { /* no argument */
4759 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4760 curproxy->check_len = strlen(DEF_CHECK_REQ);
4761 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004762 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004763 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004765 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004767 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 if (*args[4])
4769 reqlen += strlen(args[4]);
4770 else
4771 reqlen += strlen("HTTP/1.0");
4772
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004773 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004775 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004777 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4778 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004779 }
4780 else if (!strcmp(args[1], "ssl-hello-chk")) {
4781 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004784
Willy Tarreaua534fea2008-08-03 12:19:50 +02004785 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004786 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004787 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004788 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004789
4790 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
Willy Tarreau23677902007-05-08 23:50:35 +02004793 else if (!strcmp(args[1], "smtpchk")) {
4794 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004795 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004796 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004797 curproxy->options2 &= ~PR_O2_CHK_ANY;
4798 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004799
4800 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4801 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4802 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4803 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4804 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4805 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004806 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004807 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4808 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4809 } else {
4810 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4811 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4812 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4813 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4814 }
4815 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004816 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4817 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004818 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004819 else if (!strcmp(args[1], "pgsql-check")) {
4820 /* use PostgreSQL request to check servers' health */
4821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4822 err_code |= ERR_WARN;
4823
4824 free(curproxy->check_req);
4825 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004826 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004827 curproxy->options2 |= PR_O2_PGSQL_CHK;
4828
4829 if (*(args[2])) {
4830 int cur_arg = 2;
4831
4832 while (*(args[cur_arg])) {
4833 if (strcmp(args[cur_arg], "user") == 0) {
4834 char * packet;
4835 uint32_t packet_len;
4836 uint32_t pv;
4837
4838 /* suboption header - needs additional argument for it */
4839 if (*(args[cur_arg+1]) == 0) {
4840 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4841 file, linenum, args[0], args[1], args[cur_arg]);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
4845
4846 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4847 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4848 pv = htonl(0x30000); /* protocol version 3.0 */
4849
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004850 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004851
4852 memcpy(packet + 4, &pv, 4);
4853
4854 /* copy "user" */
4855 memcpy(packet + 8, "user", 4);
4856
4857 /* copy username */
4858 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4859
4860 free(curproxy->check_req);
4861 curproxy->check_req = packet;
4862 curproxy->check_len = packet_len;
4863
4864 packet_len = htonl(packet_len);
4865 memcpy(packet, &packet_len, 4);
4866 cur_arg += 2;
4867 } else {
4868 /* unknown suboption - catchall */
4869 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4870 file, linenum, args[0], args[1]);
4871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
4873 }
4874 } /* end while loop */
4875 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004876 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4877 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004878 }
4879
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004880 else if (!strcmp(args[1], "redis-check")) {
4881 /* use REDIS PING request to check servers' health */
4882 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4883 err_code |= ERR_WARN;
4884
4885 free(curproxy->check_req);
4886 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004887 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004888 curproxy->options2 |= PR_O2_REDIS_CHK;
4889
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004890 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004891 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4892 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004893
4894 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4895 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004896 }
4897
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004898 else if (!strcmp(args[1], "mysql-check")) {
4899 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4901 err_code |= ERR_WARN;
4902
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004903 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004904 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004905 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004906 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004907
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004908 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004909 * const char mysql40_client_auth_pkt[] = {
4910 * "\x0e\x00\x00" // packet length
4911 * "\x01" // packet number
4912 * "\x00\x00" // client capabilities
4913 * "\x00\x00\x01" // max packet
4914 * "haproxy\x00" // username (null terminated string)
4915 * "\x00" // filler (always 0x00)
4916 * "\x01\x00\x00" // packet length
4917 * "\x00" // packet number
4918 * "\x01" // COM_QUIT command
4919 * };
4920 */
4921
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004922 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4923 * const char mysql41_client_auth_pkt[] = {
4924 * "\x0e\x00\x00\" // packet length
4925 * "\x01" // packet number
4926 * "\x00\x00\x00\x00" // client capabilities
4927 * "\x00\x00\x00\x01" // max packet
4928 * "\x21" // character set (UTF-8)
4929 * char[23] // All zeroes
4930 * "haproxy\x00" // username (null terminated string)
4931 * "\x00" // filler (always 0x00)
4932 * "\x01\x00\x00" // packet length
4933 * "\x00" // packet number
4934 * "\x01" // COM_QUIT command
4935 * };
4936 */
4937
4938
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004939 if (*(args[2])) {
4940 int cur_arg = 2;
4941
4942 while (*(args[cur_arg])) {
4943 if (strcmp(args[cur_arg], "user") == 0) {
4944 char *mysqluser;
4945 int packetlen, reqlen, userlen;
4946
4947 /* suboption header - needs additional argument for it */
4948 if (*(args[cur_arg+1]) == 0) {
4949 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4950 file, linenum, args[0], args[1], args[cur_arg]);
4951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953 }
4954 mysqluser = args[cur_arg + 1];
4955 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004956
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004957 if (*(args[cur_arg+2])) {
4958 if (!strcmp(args[cur_arg+2], "post-41")) {
4959 packetlen = userlen + 7 + 27;
4960 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004961
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004962 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004963 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004964 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004965
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004966 snprintf(curproxy->check_req, 4, "%c%c%c",
4967 ((unsigned char) packetlen & 0xff),
4968 ((unsigned char) (packetlen >> 8) & 0xff),
4969 ((unsigned char) (packetlen >> 16) & 0xff));
4970
4971 curproxy->check_req[3] = 1;
4972 curproxy->check_req[5] = 130;
4973 curproxy->check_req[11] = 1;
4974 curproxy->check_req[12] = 33;
4975 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4976 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4977 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4978 cur_arg += 3;
4979 } else {
4980 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984 } else {
4985 packetlen = userlen + 7;
4986 reqlen = packetlen + 9;
4987
4988 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004989 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004990 curproxy->check_len = reqlen;
4991
4992 snprintf(curproxy->check_req, 4, "%c%c%c",
4993 ((unsigned char) packetlen & 0xff),
4994 ((unsigned char) (packetlen >> 8) & 0xff),
4995 ((unsigned char) (packetlen >> 16) & 0xff));
4996
4997 curproxy->check_req[3] = 1;
4998 curproxy->check_req[5] = 128;
4999 curproxy->check_req[8] = 1;
5000 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5001 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5002 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5003 cur_arg += 2;
5004 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005005 } else {
5006 /* unknown suboption - catchall */
5007 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5008 file, linenum, args[0], args[1]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012 } /* end while loop */
5013 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005014 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005015 else if (!strcmp(args[1], "ldap-check")) {
5016 /* use LDAP request to check servers' health */
5017 free(curproxy->check_req);
5018 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005019 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005020 curproxy->options2 |= PR_O2_LDAP_CHK;
5021
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005022 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005023 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5024 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005025 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5026 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005027 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005028 else if (!strcmp(args[1], "spop-check")) {
5029 if (curproxy == &defproxy) {
5030 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5031 file, linenum, args[0], args[1]);
5032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
5035 if (curproxy->cap & PR_CAP_FE) {
5036 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5037 file, linenum, args[0], args[1]);
5038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
5040 }
5041
5042 /* use SPOE request to check servers' health */
5043 free(curproxy->check_req);
5044 curproxy->check_req = NULL;
5045 curproxy->options2 &= ~PR_O2_CHK_ANY;
5046 curproxy->options2 |= PR_O2_SPOP_CHK;
5047
Christopher Faulet8ef75252017-02-20 22:56:03 +01005048 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005049 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
5052 }
5053 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5054 goto out;
5055 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005056 else if (!strcmp(args[1], "tcp-check")) {
5057 /* use raw TCPCHK send/expect to check servers' health */
5058 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5059 err_code |= ERR_WARN;
5060
5061 free(curproxy->check_req);
5062 curproxy->check_req = NULL;
5063 curproxy->options2 &= ~PR_O2_CHK_ANY;
5064 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005065 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5066 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005067 }
Simon Horman98637e52014-06-20 12:30:16 +09005068 else if (!strcmp(args[1], "external-check")) {
5069 /* excute an external command to check servers' health */
5070 free(curproxy->check_req);
5071 curproxy->check_req = NULL;
5072 curproxy->options2 &= ~PR_O2_CHK_ANY;
5073 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005074 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5075 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005076 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005077 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005078 int cur_arg;
5079
5080 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5081 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005082 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005083
Willy Tarreau87cf5142011-08-19 22:57:24 +02005084 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005085
5086 free(curproxy->fwdfor_hdr_name);
5087 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5088 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5089
5090 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5091 cur_arg = 2;
5092 while (*(args[cur_arg])) {
5093 if (!strcmp(args[cur_arg], "except")) {
5094 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005095 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005096 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005100 }
5101 /* flush useless bits */
5102 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005103 cur_arg += 2;
5104 } else if (!strcmp(args[cur_arg], "header")) {
5105 /* suboption header - needs additional argument for it */
5106 if (*(args[cur_arg+1]) == 0) {
5107 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5108 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005111 }
5112 free(curproxy->fwdfor_hdr_name);
5113 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5114 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5115 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005116 } else if (!strcmp(args[cur_arg], "if-none")) {
5117 curproxy->options &= ~PR_O_FF_ALWAYS;
5118 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005119 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005120 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005121 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005122 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005125 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005126 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005127 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005128 else if (!strcmp(args[1], "originalto")) {
5129 int cur_arg;
5130
5131 /* insert x-original-to field, but not for the IP address listed as an except.
5132 * set default options (ie: bitfield, header name, etc)
5133 */
5134
5135 curproxy->options |= PR_O_ORGTO;
5136
5137 free(curproxy->orgto_hdr_name);
5138 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5139 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5140
Willy Tarreau87cf5142011-08-19 22:57:24 +02005141 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005142 cur_arg = 2;
5143 while (*(args[cur_arg])) {
5144 if (!strcmp(args[cur_arg], "except")) {
5145 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005146 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 +02005147 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005151 }
5152 /* flush useless bits */
5153 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5154 cur_arg += 2;
5155 } else if (!strcmp(args[cur_arg], "header")) {
5156 /* suboption header - needs additional argument for it */
5157 if (*(args[cur_arg+1]) == 0) {
5158 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5159 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005162 }
5163 free(curproxy->orgto_hdr_name);
5164 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5165 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5166 cur_arg += 2;
5167 } else {
5168 /* unknown suboption - catchall */
5169 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5170 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005173 }
5174 } /* end while loop */
5175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 else {
5177 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
Willy Tarreau93893792009-07-23 13:19:11 +02005181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005183 else if (!strcmp(args[0], "default_backend")) {
5184 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005185 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005186
5187 if (*(args[1]) == 0) {
5188 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005191 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005192 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005193 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005194
5195 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5196 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005199 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005201
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005202 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5203 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 +01005204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005205 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 /* enable reconnections to dispatch */
5207 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005208
5209 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005212 else if (!strcmp(args[0], "http-reuse")) {
5213 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5214 err_code |= ERR_WARN;
5215
5216 if (strcmp(args[1], "never") == 0) {
5217 /* enable a graceful server shutdown on an HTTP 404 response */
5218 curproxy->options &= ~PR_O_REUSE_MASK;
5219 curproxy->options |= PR_O_REUSE_NEVR;
5220 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5221 goto out;
5222 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005223 else if (strcmp(args[1], "safe") == 0) {
5224 /* enable a graceful server shutdown on an HTTP 404 response */
5225 curproxy->options &= ~PR_O_REUSE_MASK;
5226 curproxy->options |= PR_O_REUSE_SAFE;
5227 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5228 goto out;
5229 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005230 else if (strcmp(args[1], "aggressive") == 0) {
5231 curproxy->options &= ~PR_O_REUSE_MASK;
5232 curproxy->options |= PR_O_REUSE_AGGR;
5233 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5234 goto out;
5235 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005236 else if (strcmp(args[1], "always") == 0) {
5237 /* enable a graceful server shutdown on an HTTP 404 response */
5238 curproxy->options &= ~PR_O_REUSE_MASK;
5239 curproxy->options |= PR_O_REUSE_ALWS;
5240 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5241 goto out;
5242 }
5243 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005244 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005249 else if (!strcmp(args[0], "http-check")) {
5250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005252
5253 if (strcmp(args[1], "disable-on-404") == 0) {
5254 /* enable a graceful server shutdown on an HTTP 404 response */
5255 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005256 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5257 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005258 }
Willy Tarreauef781042010-01-27 11:53:01 +01005259 else if (strcmp(args[1], "send-state") == 0) {
5260 /* enable emission of the apparent state of a server in HTTP checks */
5261 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005262 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5263 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005264 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005265 else if (strcmp(args[1], "expect") == 0) {
5266 const char *ptr_arg;
5267 int cur_arg;
5268
5269 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5270 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274
5275 cur_arg = 2;
5276 /* consider exclamation marks, sole or at the beginning of a word */
5277 while (*(ptr_arg = args[cur_arg])) {
5278 while (*ptr_arg == '!') {
5279 curproxy->options2 ^= PR_O2_EXP_INV;
5280 ptr_arg++;
5281 }
5282 if (*ptr_arg)
5283 break;
5284 cur_arg++;
5285 }
5286 /* now ptr_arg points to the beginning of a word past any possible
5287 * exclamation mark, and cur_arg is the argument which holds this word.
5288 */
5289 if (strcmp(ptr_arg, "status") == 0) {
5290 if (!*(args[cur_arg + 1])) {
5291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5292 file, linenum, args[0], args[1], ptr_arg);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005298 curproxy->expect_str = strdup(args[cur_arg + 1]);
5299 }
5300 else if (strcmp(ptr_arg, "string") == 0) {
5301 if (!*(args[cur_arg + 1])) {
5302 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5303 file, linenum, args[0], args[1], ptr_arg);
5304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
5306 }
5307 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005308 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005309 curproxy->expect_str = strdup(args[cur_arg + 1]);
5310 }
5311 else if (strcmp(ptr_arg, "rstatus") == 0) {
5312 if (!*(args[cur_arg + 1])) {
5313 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5314 file, linenum, args[0], args[1], ptr_arg);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005319 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005320 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005321 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005322 free(curproxy->expect_regex);
5323 curproxy->expect_regex = NULL;
5324 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005325 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005326 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5327 error = NULL;
5328 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5329 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5330 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5331 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335 }
5336 else if (strcmp(ptr_arg, "rstring") == 0) {
5337 if (!*(args[cur_arg + 1])) {
5338 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5339 file, linenum, args[0], args[1], ptr_arg);
5340 err_code |= ERR_ALERT | ERR_FATAL;
5341 goto out;
5342 }
5343 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005344 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005345 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005346 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005347 free(curproxy->expect_regex);
5348 curproxy->expect_regex = NULL;
5349 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005350 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005351 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5352 error = NULL;
5353 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5354 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5355 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5356 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 }
5361 else {
5362 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5363 file, linenum, args[0], args[1], ptr_arg);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005368 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005369 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 +02005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005372 }
5373 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005374 else if (!strcmp(args[0], "tcp-check")) {
5375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5376 err_code |= ERR_WARN;
5377
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005378 if (strcmp(args[1], "comment") == 0) {
5379 int cur_arg;
5380 struct tcpcheck_rule *tcpcheck;
5381
5382 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005383 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005384 tcpcheck->action = TCPCHK_ACT_COMMENT;
5385
5386 if (!*args[cur_arg + 1]) {
5387 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5388 file, linenum, args[cur_arg]);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
5392
5393 tcpcheck->comment = strdup(args[cur_arg + 1]);
5394
5395 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005396 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5397 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005398 }
5399 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005400 const char *ptr_arg;
5401 int cur_arg;
5402 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005403
5404 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005405 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5406 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5407 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5408 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5409 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005410
Willy Tarreau5581c272015-05-13 12:24:53 +02005411 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5412 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5413 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5414 file, linenum);
5415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005417 }
5418
5419 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005420 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005421 tcpcheck->action = TCPCHK_ACT_CONNECT;
5422
5423 /* parsing each parameters to fill up the rule */
5424 while (*(ptr_arg = args[cur_arg])) {
5425 /* tcp port */
5426 if (strcmp(args[cur_arg], "port") == 0) {
5427 if ( (atol(args[cur_arg + 1]) > 65535) ||
5428 (atol(args[cur_arg + 1]) < 1) ){
5429 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5430 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434 tcpcheck->port = atol(args[cur_arg + 1]);
5435 cur_arg += 2;
5436 }
5437 /* send proxy protocol */
5438 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5439 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5440 cur_arg++;
5441 }
5442#ifdef USE_OPENSSL
5443 else if (strcmp(args[cur_arg], "ssl") == 0) {
5444 curproxy->options |= PR_O_TCPCHK_SSL;
5445 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5446 cur_arg++;
5447 }
5448#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005449 /* comment for this tcpcheck line */
5450 else if (strcmp(args[cur_arg], "comment") == 0) {
5451 if (!*args[cur_arg + 1]) {
5452 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5453 file, linenum, args[cur_arg]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457 tcpcheck->comment = strdup(args[cur_arg + 1]);
5458 cur_arg += 2;
5459 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005460 else {
5461#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005462 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 +01005463#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005464 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 +01005465#endif /* USE_OPENSSL */
5466 file, linenum, args[0], args[1], args[cur_arg]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470
5471 }
5472
5473 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5474 }
5475 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005476 if (! *(args[2]) ) {
5477 /* SEND string expected */
5478 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5479 file, linenum, args[0], args[1], args[2]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 } else {
5483 struct tcpcheck_rule *tcpcheck;
5484
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005485 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005486
5487 tcpcheck->action = TCPCHK_ACT_SEND;
5488 tcpcheck->string_len = strlen(args[2]);
5489 tcpcheck->string = strdup(args[2]);
5490 tcpcheck->expect_regex = NULL;
5491
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005492 /* comment for this tcpcheck line */
5493 if (strcmp(args[3], "comment") == 0) {
5494 if (!*args[4]) {
5495 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5496 file, linenum, args[3]);
5497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
5499 }
5500 tcpcheck->comment = strdup(args[4]);
5501 }
5502
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005503 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5504 }
5505 }
5506 else if (strcmp(args[1], "send-binary") == 0) {
5507 if (! *(args[2]) ) {
5508 /* SEND binary string expected */
5509 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5510 file, linenum, args[0], args[1], args[2]);
5511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
5513 } else {
5514 struct tcpcheck_rule *tcpcheck;
5515 char *err = NULL;
5516
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005517 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005518
5519 tcpcheck->action = TCPCHK_ACT_SEND;
5520 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5521 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5522 file, linenum, args[0], args[1], args[2], err);
5523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
5525 }
5526 tcpcheck->expect_regex = NULL;
5527
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005528 /* comment for this tcpcheck line */
5529 if (strcmp(args[3], "comment") == 0) {
5530 if (!*args[4]) {
5531 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5532 file, linenum, args[3]);
5533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
5535 }
5536 tcpcheck->comment = strdup(args[4]);
5537 }
5538
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005539 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5540 }
5541 }
5542 else if (strcmp(args[1], "expect") == 0) {
5543 const char *ptr_arg;
5544 int cur_arg;
5545 int inverse = 0;
5546
5547 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5548 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
5552
5553 cur_arg = 2;
5554 /* consider exclamation marks, sole or at the beginning of a word */
5555 while (*(ptr_arg = args[cur_arg])) {
5556 while (*ptr_arg == '!') {
5557 inverse = !inverse;
5558 ptr_arg++;
5559 }
5560 if (*ptr_arg)
5561 break;
5562 cur_arg++;
5563 }
5564 /* now ptr_arg points to the beginning of a word past any possible
5565 * exclamation mark, and cur_arg is the argument which holds this word.
5566 */
5567 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005568 struct tcpcheck_rule *tcpcheck;
5569 char *err = NULL;
5570
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005571 if (!*(args[cur_arg + 1])) {
5572 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5573 file, linenum, args[0], args[1], ptr_arg);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005577
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005578 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579
5580 tcpcheck->action = TCPCHK_ACT_EXPECT;
5581 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5582 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5583 file, linenum, args[0], args[1], args[2], err);
5584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
5586 }
5587 tcpcheck->expect_regex = NULL;
5588 tcpcheck->inverse = inverse;
5589
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005590 /* tcpcheck comment */
5591 cur_arg += 2;
5592 if (strcmp(args[cur_arg], "comment") == 0) {
5593 if (!*args[cur_arg + 1]) {
5594 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5595 file, linenum, args[cur_arg + 1]);
5596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
5598 }
5599 tcpcheck->comment = strdup(args[cur_arg + 1]);
5600 }
5601
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005602 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5603 }
5604 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005605 struct tcpcheck_rule *tcpcheck;
5606
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005607 if (!*(args[cur_arg + 1])) {
5608 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5609 file, linenum, args[0], args[1], ptr_arg);
5610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005613
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005614 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005615
5616 tcpcheck->action = TCPCHK_ACT_EXPECT;
5617 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5618 tcpcheck->string = strdup(args[cur_arg + 1]);
5619 tcpcheck->expect_regex = NULL;
5620 tcpcheck->inverse = inverse;
5621
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005622 /* tcpcheck comment */
5623 cur_arg += 2;
5624 if (strcmp(args[cur_arg], "comment") == 0) {
5625 if (!*args[cur_arg + 1]) {
5626 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5627 file, linenum, args[cur_arg + 1]);
5628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
5630 }
5631 tcpcheck->comment = strdup(args[cur_arg + 1]);
5632 }
5633
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005634 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5635 }
5636 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005637 struct tcpcheck_rule *tcpcheck;
5638
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005639 if (!*(args[cur_arg + 1])) {
5640 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5641 file, linenum, args[0], args[1], ptr_arg);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005645
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005646 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005647
5648 tcpcheck->action = TCPCHK_ACT_EXPECT;
5649 tcpcheck->string_len = 0;
5650 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005651 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5652 error = NULL;
5653 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5654 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5655 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5656 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660 tcpcheck->inverse = inverse;
5661
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005662 /* tcpcheck comment */
5663 cur_arg += 2;
5664 if (strcmp(args[cur_arg], "comment") == 0) {
5665 if (!*args[cur_arg + 1]) {
5666 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5667 file, linenum, args[cur_arg + 1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671 tcpcheck->comment = strdup(args[cur_arg + 1]);
5672 }
5673
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005674 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5675 }
5676 else {
5677 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5678 file, linenum, args[0], args[1], ptr_arg);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
5682 }
5683 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005684 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
5687 }
5688 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005689 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005690 if (curproxy == &defproxy) {
5691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005692 err_code |= ERR_ALERT | ERR_FATAL;
5693 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005694 }
5695
Willy Tarreaub80c2302007-11-30 20:51:32 +01005696 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005697 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005698
5699 if (strcmp(args[1], "fail") == 0) {
5700 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005701 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005702 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5703 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005706 }
5707
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005708 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5709 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5710 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005713 }
5714 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5715 }
5716 else {
5717 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005720 }
5721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722#ifdef TPROXY
5723 else if (!strcmp(args[0], "transparent")) {
5724 /* enable transparent proxy connections */
5725 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005726 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 }
5729#endif
5730 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005731 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005732 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005733
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 if (*(args[1]) == 0) {
5735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
5739 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005740 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005743 else if (!strcmp(args[0], "backlog")) { /* backlog */
5744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005745 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005746
5747 if (*(args[1]) == 0) {
5748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005751 }
5752 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5754 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005755 }
Willy Tarreau86034312006-12-29 00:10:33 +01005756 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005759
Willy Tarreau86034312006-12-29 00:10:33 +01005760 if (*(args[1]) == 0) {
5761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005764 }
5765 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005766 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5767 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5770 if (*(args[1]) == 0) {
5771 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005775 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5776 if (err) {
5777 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5778 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005781 }
5782 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005787 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005788 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005789 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005790
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 if (curproxy == &defproxy) {
5792 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005796 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005798
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005799 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005800 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005801 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005802 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005803 goto out;
5804 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005805
5806 proto = protocol_by_family(sk->ss_family);
5807 if (!proto || !proto->connect) {
5808 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5809 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
5812 }
5813
5814 if (port1 != port2) {
5815 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5816 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005820
5821 if (!port1) {
5822 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5823 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
5826 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005827
William Lallemanddf1425a2015-04-28 20:17:49 +02005828 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5829 goto out;
5830
Willy Tarreaud5191e72010-02-09 20:50:45 +01005831 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005832 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
5834 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005837
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005838 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5839 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005844 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005845 /**
5846 * The syntax for hash-type config element is
5847 * hash-type {map-based|consistent} [[<algo>] avalanche]
5848 *
5849 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5850 */
5851 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005852
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5854 err_code |= ERR_WARN;
5855
5856 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005857 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5858 }
5859 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005860 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5861 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005862 else if (strcmp(args[1], "avalanche") == 0) {
5863 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]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005866 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005867 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005868 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871 }
Bhaskar98634f02013-10-29 23:30:51 -04005872
5873 /* set the hash function to use */
5874 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005875 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005876 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005877
5878 /* if consistent with no argument, then avalanche modifier is also applied */
5879 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5880 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005881 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005882 /* set the hash function */
5883 if (!strcmp(args[2], "sdbm")) {
5884 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5885 }
5886 else if (!strcmp(args[2], "djb2")) {
5887 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005888 }
5889 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005890 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005891 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005892 else if (!strcmp(args[2], "crc32")) {
5893 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5894 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005895 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005896 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 -05005897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900
5901 /* set the hash modifier */
5902 if (!strcmp(args[3], "avalanche")) {
5903 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5904 }
5905 else if (*args[3]) {
5906 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005910 }
William Lallemanda73203e2012-03-12 12:48:57 +01005911 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005912 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5913 if (*(args[1]) == 0) {
5914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
5917 }
5918 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5919 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5920 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
5923 }
5924 }
William Lallemanda73203e2012-03-12 12:48:57 +01005925 else if (strcmp(args[0], "unique-id-format") == 0) {
5926 if (!*(args[1])) {
5927 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
5930 }
William Lallemand3203ff42012-11-11 17:30:56 +01005931 if (*(args[2])) {
5932 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005936 free(curproxy->conf.uniqueid_format_string);
5937 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005938
Willy Tarreau62a61232013-04-12 18:13:46 +02005939 free(curproxy->conf.uif_file);
5940 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5941 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005942 }
William Lallemanda73203e2012-03-12 12:48:57 +01005943
5944 else if (strcmp(args[0], "unique-id-header") == 0) {
5945 if (!*(args[1])) {
5946 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5947 err_code |= ERR_ALERT | ERR_FATAL;
5948 goto out;
5949 }
5950 free(curproxy->header_unique_id);
5951 curproxy->header_unique_id = strdup(args[1]);
5952 }
5953
William Lallemand723b73a2012-02-08 16:37:49 +01005954 else if (strcmp(args[0], "log-format") == 0) {
5955 if (!*(args[1])) {
5956 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
William Lallemand3203ff42012-11-11 17:30:56 +01005960 if (*(args[2])) {
5961 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005965 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5966 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005967
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005968 if (curproxy->conf.logformat_string == default_http_log_format)
5969 oldlogformat = "option httplog";
5970 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5971 oldlogformat = "option tcplog";
5972 else if (curproxy->conf.logformat_string == clf_http_log_format)
5973 oldlogformat = "option httplog clf";
5974 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5975 file, linenum, oldlogformat);
5976 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005977 if (curproxy->conf.logformat_string != default_http_log_format &&
5978 curproxy->conf.logformat_string != default_tcp_log_format &&
5979 curproxy->conf.logformat_string != clf_http_log_format)
5980 free(curproxy->conf.logformat_string);
5981 curproxy->conf.logformat_string = strdup(args[1]);
5982
5983 free(curproxy->conf.lfs_file);
5984 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5985 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005986
5987 /* get a chance to improve log-format error reporting by
5988 * reporting the correct line-number when possible.
5989 */
5990 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5991 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5992 file, linenum, curproxy->id);
5993 err_code |= ERR_WARN;
5994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005996 else if (!strcmp(args[0], "log-format-sd")) {
5997 if (!*(args[1])) {
5998 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5999 err_code |= ERR_ALERT | ERR_FATAL;
6000 goto out;
6001 }
6002 if (*(args[2])) {
6003 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007
6008 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6009 free(curproxy->conf.logformat_sd_string);
6010 curproxy->conf.logformat_sd_string = strdup(args[1]);
6011
6012 free(curproxy->conf.lfsd_file);
6013 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6014 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6015
6016 /* get a chance to improve log-format-sd error reporting by
6017 * reporting the correct line-number when possible.
6018 */
6019 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6020 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6021 file, linenum, curproxy->id);
6022 err_code |= ERR_WARN;
6023 }
6024 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006025 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6026 if (*(args[1]) == 0) {
6027 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6028 err_code |= ERR_ALERT | ERR_FATAL;
6029 goto out;
6030 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006031 chunk_destroy(&curproxy->log_tag);
6032 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006033 }
William Lallemand0f99e342011-10-12 17:50:54 +02006034 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6035 /* delete previous herited or defined syslog servers */
6036 struct logsrv *back;
6037
6038 if (*(args[1]) != 0) {
6039 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6040 err_code |= ERR_ALERT | ERR_FATAL;
6041 goto out;
6042 }
6043
William Lallemand723b73a2012-02-08 16:37:49 +01006044 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6045 LIST_DEL(&tmplogsrv->list);
6046 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006047 }
6048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006050 struct logsrv *logsrv;
6051
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006053 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006054 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006055 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006056 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006057 LIST_INIT(&node->list);
6058 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 }
6061 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006062 struct sockaddr_storage *sk;
6063 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006064 int arg = 0;
6065 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006066
Vincent Bernat02779b62016-04-03 13:48:43 +02006067 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006068
Willy Tarreau18324f52014-06-27 18:10:07 +02006069 /* just after the address, a length may be specified */
6070 if (strcmp(args[arg+2], "len") == 0) {
6071 len = atoi(args[arg+3]);
6072 if (len < 80 || len > 65535) {
6073 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6074 file, linenum, args[arg+3]);
6075 err_code |= ERR_ALERT | ERR_FATAL;
6076 goto out;
6077 }
6078 logsrv->maxlen = len;
6079
6080 /* skip these two args */
6081 arg += 2;
6082 }
6083 else
6084 logsrv->maxlen = MAX_SYSLOG_LEN;
6085
6086 if (logsrv->maxlen > global.max_syslog_len) {
6087 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006088 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6089 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6090 logline = my_realloc2(logline, global.max_syslog_len + 1);
6091 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006092 }
6093
Dragan Dosen1322d092015-09-22 16:05:32 +02006094 /* after the length, a format may be specified */
6095 if (strcmp(args[arg+2], "format") == 0) {
6096 logsrv->format = get_log_format(args[arg+3]);
6097 if (logsrv->format < 0) {
6098 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6099 err_code |= ERR_ALERT | ERR_FATAL;
6100 goto out;
6101 }
6102
6103 /* skip these two args */
6104 arg += 2;
6105 }
6106
William Lallemanddf1425a2015-04-28 20:17:49 +02006107 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6108 goto out;
6109
Willy Tarreau18324f52014-06-27 18:10:07 +02006110 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006111 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006112 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
6115
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 }
6117
William Lallemand0f99e342011-10-12 17:50:54 +02006118 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006119 if (*(args[arg+3])) {
6120 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006121 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006122 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006123 err_code |= ERR_ALERT | ERR_FATAL;
6124 goto out;
6125
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 }
6127 }
6128
William Lallemand0f99e342011-10-12 17:50:54 +02006129 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006130 if (*(args[arg+4])) {
6131 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006132 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006133 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006134 err_code |= ERR_ALERT | ERR_FATAL;
6135 goto out;
6136
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006137 }
6138 }
6139
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006140 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006141 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006142 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006143 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006144 goto out;
6145 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006147 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006148
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006149 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006150 if (port1 != port2) {
6151 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6152 file, linenum, args[0], args[1]);
6153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155 }
6156
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006157 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006158 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 }
William Lallemand0f99e342011-10-12 17:50:54 +02006160
6161 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 }
6163 else {
6164 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006166 err_code |= ERR_ALERT | ERR_FATAL;
6167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 }
6169 }
6170 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006171 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006172 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006173 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006174 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006175
Willy Tarreau977b8e42006-12-29 14:19:17 +01006176 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006177 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006178
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006180 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6181 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006185
6186 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006187 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6188 free(curproxy->conn_src.iface_name);
6189 curproxy->conn_src.iface_name = NULL;
6190 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006191
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006192 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006193 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006194 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006195 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006196 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006197 goto out;
6198 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006199
6200 proto = protocol_by_family(sk->ss_family);
6201 if (!proto || !proto->connect) {
6202 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006203 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006204 err_code |= ERR_ALERT | ERR_FATAL;
6205 goto out;
6206 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006207
6208 if (port1 != port2) {
6209 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6210 file, linenum, args[0], args[1]);
6211 err_code |= ERR_ALERT | ERR_FATAL;
6212 goto out;
6213 }
6214
Willy Tarreauef9a3602012-12-08 22:29:20 +01006215 curproxy->conn_src.source_addr = *sk;
6216 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006217
6218 cur_arg = 2;
6219 while (*(args[cur_arg])) {
6220 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006221#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006222 if (!*args[cur_arg + 1]) {
6223 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6224 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006225 err_code |= ERR_ALERT | ERR_FATAL;
6226 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006227 }
6228
6229 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006230 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6231 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006232 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006233 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6234 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006235 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6236 char *name, *end;
6237
6238 name = args[cur_arg+1] + 7;
6239 while (isspace(*name))
6240 name++;
6241
6242 end = name;
6243 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6244 end++;
6245
Willy Tarreauef9a3602012-12-08 22:29:20 +01006246 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6247 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6248 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6249 curproxy->conn_src.bind_hdr_len = end - name;
6250 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6251 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6252 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006253
6254 /* now look for an occurrence number */
6255 while (isspace(*end))
6256 end++;
6257 if (*end == ',') {
6258 end++;
6259 name = end;
6260 if (*end == '-')
6261 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006262 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006263 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006264 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006265 }
6266
Willy Tarreauef9a3602012-12-08 22:29:20 +01006267 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006268 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6269 " occurrences values smaller than %d.\n",
6270 file, linenum, MAX_HDR_HISTORY);
6271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
6273 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006274 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006275 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006276
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006277 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006278 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006280 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006282 goto out;
6283 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006284
6285 proto = protocol_by_family(sk->ss_family);
6286 if (!proto || !proto->connect) {
6287 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6288 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
6291 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006292
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006293 if (port1 != port2) {
6294 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6295 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006296 err_code |= ERR_ALERT | ERR_FATAL;
6297 goto out;
6298 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006299 curproxy->conn_src.tproxy_addr = *sk;
6300 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006301 }
6302 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006303#else /* no TPROXY support */
6304 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006305 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006308#endif
6309 cur_arg += 2;
6310 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006311 }
6312
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006313 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6314#ifdef SO_BINDTODEVICE
6315 if (!*args[cur_arg + 1]) {
6316 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006320 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006321 free(curproxy->conn_src.iface_name);
6322 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6323 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006324 global.last_checks |= LSTCHK_NETADM;
6325#else
6326 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6327 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006330#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006331 cur_arg += 2;
6332 continue;
6333 }
6334 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006335 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006336 err_code |= ERR_ALERT | ERR_FATAL;
6337 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006340 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6341 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6342 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006343 err_code |= ERR_ALERT | ERR_FATAL;
6344 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6349 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006350 err_code |= ERR_ALERT | ERR_FATAL;
6351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353
6354 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006355 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006356 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
6360 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006362 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006363 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 }
6367 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006369 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006370 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 }
6374 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006376 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006377 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
6381 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006383 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006384 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006388 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006390 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006391 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006393 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006399 err_code |= ERR_ALERT | ERR_FATAL;
6400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402
6403 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006404 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006405 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 }
6409 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006411 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006412 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 }
6416 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006418 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006419 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
6423 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006425 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006426 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 }
6430 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006432 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006433 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006437 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006439 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006440 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006441 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006442 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006445 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006446
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 if (curproxy == &defproxy) {
6448 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006452 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 if (*(args[1]) == 0) {
6456 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006457 err_code |= ERR_ALERT | ERR_FATAL;
6458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006460
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006461 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006462 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6463 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6464 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006465 err_code |= ERR_ALERT | ERR_FATAL;
6466 goto out;
6467 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006468 err_code |= warnif_cond_conflicts(cond,
6469 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6470 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006471 }
6472 else if (*args[2]) {
6473 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6474 file, linenum, args[0], args[2]);
6475 err_code |= ERR_ALERT | ERR_FATAL;
6476 goto out;
6477 }
6478
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006479 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006480 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006481 wl->s = strdup(args[1]);
6482 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006483 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
6485 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6488 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006489 err_code |= ERR_ALERT | ERR_FATAL;
6490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006492
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006495 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
6506 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006508 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006509 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
6513 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006514 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006517 err_code |= ERR_ALERT | ERR_FATAL;
6518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 }
6520
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006522 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006523 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 }
6527 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006529 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006530 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006531 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 }
6534 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006535 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006536 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006537 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006538 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 }
6541 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006542 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006543
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 if (curproxy == &defproxy) {
6545 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006546 err_code |= ERR_ALERT | ERR_FATAL;
6547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006549 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006550 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 if (*(args[1]) == 0) {
6553 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006554 err_code |= ERR_ALERT | ERR_FATAL;
6555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 }
6557
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006558 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006559 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6560 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6561 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006562 err_code |= ERR_ALERT | ERR_FATAL;
6563 goto out;
6564 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006565 err_code |= warnif_cond_conflicts(cond,
6566 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6567 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006568 }
6569 else if (*args[2]) {
6570 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6571 file, linenum, args[0], args[2]);
6572 err_code |= ERR_ALERT | ERR_FATAL;
6573 goto out;
6574 }
6575
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006576 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006577 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006578 wl->s = strdup(args[1]);
6579 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 }
6581 else if (!strcmp(args[0], "errorloc") ||
6582 !strcmp(args[0], "errorloc302") ||
6583 !strcmp(args[0], "errorloc303")) { /* error location */
6584 int errnum, errlen;
6585 char *err;
6586
Willy Tarreau977b8e42006-12-29 14:19:17 +01006587 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006588 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006589
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006591 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006592 err_code |= ERR_ALERT | ERR_FATAL;
6593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 }
6595
6596 errnum = atol(args[1]);
6597 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006598 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6599 err = malloc(errlen);
6600 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006602 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6603 err = malloc(errlen);
6604 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 }
6606
Willy Tarreau0f772532006-12-23 20:51:41 +01006607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6608 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006609 chunk_destroy(&curproxy->errmsg[rc]);
6610 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006611 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006614
6615 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006616 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6617 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006618 free(err);
6619 }
6620 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006621 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6622 int errnum, errlen, fd;
6623 char *err;
6624 struct stat stat;
6625
6626 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006627 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006628
6629 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006630 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006631 err_code |= ERR_ALERT | ERR_FATAL;
6632 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006633 }
6634
6635 fd = open(args[2], O_RDONLY);
6636 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6637 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6638 file, linenum, args[2], args[1]);
6639 if (fd >= 0)
6640 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006641 err_code |= ERR_ALERT | ERR_FATAL;
6642 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006643 }
6644
Willy Tarreau27a674e2009-08-17 07:23:33 +02006645 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006646 errlen = stat.st_size;
6647 } else {
6648 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006649 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006650 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006651 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006652 }
6653
6654 err = malloc(errlen); /* malloc() must succeed during parsing */
6655 errnum = read(fd, err, errlen);
6656 if (errnum != errlen) {
6657 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6658 file, linenum, args[2], args[1]);
6659 close(fd);
6660 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006661 err_code |= ERR_ALERT | ERR_FATAL;
6662 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006663 }
6664 close(fd);
6665
6666 errnum = atol(args[1]);
6667 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6668 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006669 chunk_destroy(&curproxy->errmsg[rc]);
6670 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006671 break;
6672 }
6673 }
6674
6675 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006676 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6677 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006678 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006679 free(err);
6680 }
6681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006682 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006683 struct cfg_kw_list *kwl;
6684 int index;
6685
6686 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6687 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6688 if (kwl->kw[index].section != CFG_LISTEN)
6689 continue;
6690 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6691 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006692 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006693 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006694 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006695 err_code |= ERR_ALERT | ERR_FATAL;
6696 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006697 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006698 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006699 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006700 err_code |= ERR_WARN;
6701 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006702 }
Willy Tarreau93893792009-07-23 13:19:11 +02006703 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006704 }
6705 }
6706 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006707
Willy Tarreau6daf3432008-01-22 16:44:08 +01006708 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006709 err_code |= ERR_ALERT | ERR_FATAL;
6710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711 }
Willy Tarreau93893792009-07-23 13:19:11 +02006712 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006713 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006714 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006715}
6716
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006717int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006718cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6719{
6720#ifdef CONFIG_HAP_NS
6721 const char *err;
6722 const char *item = args[0];
6723
6724 if (!strcmp(item, "namespace_list")) {
6725 return 0;
6726 }
6727 else if (!strcmp(item, "namespace")) {
6728 size_t idx = 1;
6729 const char *current;
6730 while (*(current = args[idx++])) {
6731 err = invalid_char(current);
6732 if (err) {
6733 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6734 file, linenum, *err, item, current);
6735 return ERR_ALERT | ERR_FATAL;
6736 }
6737
6738 if (netns_store_lookup(current, strlen(current))) {
6739 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6740 file, linenum, current);
6741 return ERR_ALERT | ERR_FATAL;
6742 }
6743 if (!netns_store_insert(current)) {
6744 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6745 file, linenum, current);
6746 return ERR_ALERT | ERR_FATAL;
6747 }
6748 }
6749 }
6750
6751 return 0;
6752#else
6753 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6754 file, linenum);
6755 return ERR_ALERT | ERR_FATAL;
6756#endif
6757}
6758
6759int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006760cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6761{
6762
6763 int err_code = 0;
6764 const char *err;
6765
6766 if (!strcmp(args[0], "userlist")) { /* new userlist */
6767 struct userlist *newul;
6768
6769 if (!*args[1]) {
6770 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6771 file, linenum, args[0]);
6772 err_code |= ERR_ALERT | ERR_FATAL;
6773 goto out;
6774 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6776 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006777
6778 err = invalid_char(args[1]);
6779 if (err) {
6780 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6781 file, linenum, *err, args[0], args[1]);
6782 err_code |= ERR_ALERT | ERR_FATAL;
6783 goto out;
6784 }
6785
6786 for (newul = userlist; newul; newul = newul->next)
6787 if (!strcmp(newul->name, args[1])) {
6788 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6789 file, linenum, args[1]);
6790 err_code |= ERR_WARN;
6791 goto out;
6792 }
6793
Vincent Bernat02779b62016-04-03 13:48:43 +02006794 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 if (!newul) {
6796 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6797 err_code |= ERR_ALERT | ERR_ABORT;
6798 goto out;
6799 }
6800
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006801 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006802 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6804 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006805 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006806 goto out;
6807 }
6808
6809 newul->next = userlist;
6810 userlist = newul;
6811
6812 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006813 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006815 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006816
6817 if (!*args[1]) {
6818 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6819 file, linenum, args[0]);
6820 err_code |= ERR_ALERT | ERR_FATAL;
6821 goto out;
6822 }
6823
6824 err = invalid_char(args[1]);
6825 if (err) {
6826 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6827 file, linenum, *err, args[0], args[1]);
6828 err_code |= ERR_ALERT | ERR_FATAL;
6829 goto out;
6830 }
6831
William Lallemand4ac9f542015-05-28 18:03:51 +02006832 if (!userlist)
6833 goto out;
6834
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006835 for (ag = userlist->groups; ag; ag = ag->next)
6836 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6838 file, linenum, args[1], userlist->name);
6839 err_code |= ERR_ALERT;
6840 goto out;
6841 }
6842
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006843 ag = calloc(1, sizeof(*ag));
6844 if (!ag) {
6845 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6846 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006847 goto out;
6848 }
6849
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006850 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006851 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006852 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6853 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006854 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006855 goto out;
6856 }
6857
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006858 cur_arg = 2;
6859
6860 while (*args[cur_arg]) {
6861 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006862 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006863 cur_arg += 2;
6864 continue;
6865 } else {
6866 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6867 file, linenum, args[0]);
6868 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006869 free(ag->groupusers);
6870 free(ag->name);
6871 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 goto out;
6873 }
6874 }
6875
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006876 ag->next = userlist->groups;
6877 userlist->groups = ag;
6878
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006879 } else if (!strcmp(args[0], "user")) { /* new user */
6880 struct auth_users *newuser;
6881 int cur_arg;
6882
6883 if (!*args[1]) {
6884 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6885 file, linenum, args[0]);
6886 err_code |= ERR_ALERT | ERR_FATAL;
6887 goto out;
6888 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006889 if (!userlist)
6890 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006891
6892 for (newuser = userlist->users; newuser; newuser = newuser->next)
6893 if (!strcmp(newuser->user, args[1])) {
6894 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6895 file, linenum, args[1], userlist->name);
6896 err_code |= ERR_ALERT;
6897 goto out;
6898 }
6899
Vincent Bernat02779b62016-04-03 13:48:43 +02006900 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006901 if (!newuser) {
6902 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6903 err_code |= ERR_ALERT | ERR_ABORT;
6904 goto out;
6905 }
6906
6907 newuser->user = strdup(args[1]);
6908
6909 newuser->next = userlist->users;
6910 userlist->users = newuser;
6911
6912 cur_arg = 2;
6913
6914 while (*args[cur_arg]) {
6915 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006916#ifdef CONFIG_HAP_CRYPT
6917 if (!crypt("", args[cur_arg + 1])) {
6918 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6919 file, linenum, newuser->user);
6920 err_code |= ERR_ALERT | ERR_FATAL;
6921 goto out;
6922 }
6923#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006924 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6925 file, linenum);
6926 err_code |= ERR_ALERT;
6927#endif
6928 newuser->pass = strdup(args[cur_arg + 1]);
6929 cur_arg += 2;
6930 continue;
6931 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6932 newuser->pass = strdup(args[cur_arg + 1]);
6933 newuser->flags |= AU_O_INSECURE;
6934 cur_arg += 2;
6935 continue;
6936 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006937 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006938 cur_arg += 2;
6939 continue;
6940 } else {
6941 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6942 file, linenum, args[0]);
6943 err_code |= ERR_ALERT | ERR_FATAL;
6944 goto out;
6945 }
6946 }
6947 } else {
6948 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6949 err_code |= ERR_ALERT | ERR_FATAL;
6950 }
6951
6952out:
6953 return err_code;
6954}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006955
Christopher Faulet79bdef32016-11-04 22:36:15 +01006956int
6957cfg_parse_scope(const char *file, int linenum, char *line)
6958{
6959 char *beg, *end, *scope = NULL;
6960 int err_code = 0;
6961 const char *err;
6962
6963 beg = line + 1;
6964 end = strchr(beg, ']');
6965
6966 /* Detect end of scope declaration */
6967 if (!end || end == beg) {
6968 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6969 file, linenum);
6970 err_code |= ERR_ALERT | ERR_FATAL;
6971 goto out;
6972 }
6973
6974 /* Get scope name and check its validity */
6975 scope = my_strndup(beg, end-beg);
6976 err = invalid_char(scope);
6977 if (err) {
6978 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6979 file, linenum, *err);
6980 err_code |= ERR_ALERT | ERR_ABORT;
6981 goto out;
6982 }
6983
6984 /* Be sure to have a scope declaration alone on its line */
6985 line = end+1;
6986 while (isspace((unsigned char)*line))
6987 line++;
6988 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6989 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6990 file, linenum, *line);
6991 err_code |= ERR_ALERT | ERR_ABORT;
6992 goto out;
6993 }
6994
6995 /* We have a valid scope declaration, save it */
6996 free(cfg_scope);
6997 cfg_scope = scope;
6998 scope = NULL;
6999
7000 out:
7001 free(scope);
7002 return err_code;
7003}
7004
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005/*
7006 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007007 * Returns the error code, 0 if OK, or any combination of :
7008 * - ERR_ABORT: must abort ASAP
7009 * - ERR_FATAL: we can continue parsing but not start the service
7010 * - ERR_WARN: a warning has been emitted
7011 * - ERR_ALERT: an alert has been emitted
7012 * Only the two first ones can stop processing, the two others are just
7013 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007014 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007015int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016{
William Lallemand64e84512015-05-12 14:25:37 +02007017 char *thisline;
7018 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 FILE *f;
7020 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007021 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007022 struct cfg_section *cs = NULL;
7023 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007024 int readbytes = 0;
7025
7026 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007027 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007028 return -1;
7029 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007030
David Carlier97880bb2016-04-08 10:35:26 +01007031 if ((f=fopen(file,"r")) == NULL) {
7032 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007033 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007035
William Lallemandb2f07452015-05-12 14:27:13 +02007036next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007037 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007038 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007039 char *end;
7040 char *args[MAX_LINE_ARGS + 1];
7041 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007042 int dquote = 0; /* double quote */
7043 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007044
Willy Tarreaubaaee002006-06-26 02:48:02 +02007045 linenum++;
7046
7047 end = line + strlen(line);
7048
William Lallemand64e84512015-05-12 14:25:37 +02007049 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007050 /* Check if we reached the limit and the last char is not \n.
7051 * Watch out for the last line without the terminating '\n'!
7052 */
William Lallemand64e84512015-05-12 14:25:37 +02007053 char *newline;
7054 int newlinesize = linesize * 2;
7055
7056 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7057 if (newline == NULL) {
7058 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7059 file, linenum);
7060 err_code |= ERR_ALERT | ERR_FATAL;
7061 continue;
7062 }
7063
7064 readbytes = linesize - 1;
7065 linesize = newlinesize;
7066 thisline = newline;
7067 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007068 }
7069
William Lallemand64e84512015-05-12 14:25:37 +02007070 readbytes = 0;
7071
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007073 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007074 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007075
Christopher Faulet79bdef32016-11-04 22:36:15 +01007076
7077 if (*line == '[') {/* This is the begining if a scope */
7078 err_code |= cfg_parse_scope(file, linenum, line);
7079 goto next_line;
7080 }
7081
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082 arg = 0;
7083 args[arg] = line;
7084
7085 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007086 if (*line == '"' && !squote) { /* double quote outside single quotes */
7087 if (dquote)
7088 dquote = 0;
7089 else
7090 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007091 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007092 end--;
7093 }
7094 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7095 if (squote)
7096 squote = 0;
7097 else
7098 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007099 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007100 end--;
7101 }
7102 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7104 * C equivalent value. Other combinations left unchanged (eg: \1).
7105 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007106 int skip = 0;
7107 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7108 *line = line[1];
7109 skip = 1;
7110 }
7111 else if (line[1] == 'r') {
7112 *line = '\r';
7113 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007115 else if (line[1] == 'n') {
7116 *line = '\n';
7117 skip = 1;
7118 }
7119 else if (line[1] == 't') {
7120 *line = '\t';
7121 skip = 1;
7122 }
7123 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007124 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007125 unsigned char hex1, hex2;
7126 hex1 = toupper(line[2]) - '0';
7127 hex2 = toupper(line[3]) - '0';
7128 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7129 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7130 *line = (hex1<<4) + hex2;
7131 skip = 3;
7132 }
7133 else {
7134 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007135 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007136 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007137 } else if (line[1] == '"') {
7138 *line = '"';
7139 skip = 1;
7140 } else if (line[1] == '\'') {
7141 *line = '\'';
7142 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007143 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7144 *line = '$';
7145 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 }
7147 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007148 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007149 end -= skip;
7150 }
7151 line++;
7152 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007153 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007154 /* end of string, end of loop */
7155 *line = 0;
7156 break;
7157 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007158 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007160 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007161 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007162 line++;
7163 args[++arg] = line;
7164 }
William Lallemandb2f07452015-05-12 14:27:13 +02007165 else if (dquote && *line == '$') {
7166 /* environment variables are evaluated inside double quotes */
7167 char *var_beg;
7168 char *var_end;
7169 char save_char;
7170 char *value;
7171 int val_len;
7172 int newlinesize;
7173 int braces = 0;
7174
7175 var_beg = line + 1;
7176 var_end = var_beg;
7177
7178 if (*var_beg == '{') {
7179 var_beg++;
7180 var_end++;
7181 braces = 1;
7182 }
7183
7184 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7185 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7186 err_code |= ERR_ALERT | ERR_FATAL;
7187 goto next_line; /* skip current line */
7188 }
7189
7190 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7191 var_end++;
7192
7193 save_char = *var_end;
7194 *var_end = '\0';
7195 value = getenv(var_beg);
7196 *var_end = save_char;
7197 val_len = value ? strlen(value) : 0;
7198
7199 if (braces) {
7200 if (*var_end == '}') {
7201 var_end++;
7202 braces = 0;
7203 } else {
7204 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7205 err_code |= ERR_ALERT | ERR_FATAL;
7206 goto next_line; /* skip current line */
7207 }
7208 }
7209
7210 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7211
7212 /* if not enough space in thisline */
7213 if (newlinesize > linesize) {
7214 char *newline;
7215
7216 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7217 if (newline == NULL) {
7218 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7219 err_code |= ERR_ALERT | ERR_FATAL;
7220 goto next_line; /* slip current line */
7221 }
7222 /* recompute pointers if realloc returns a new pointer */
7223 if (newline != thisline) {
7224 int i;
7225 int diff;
7226
7227 for (i = 0; i <= arg; i++) {
7228 diff = args[i] - thisline;
7229 args[i] = newline + diff;
7230 }
7231
7232 diff = var_end - thisline;
7233 var_end = newline + diff;
7234 diff = end - thisline;
7235 end = newline + diff;
7236 diff = line - thisline;
7237 line = newline + diff;
7238 thisline = newline;
7239 }
7240 linesize = newlinesize;
7241 }
7242
7243 /* insert value inside the line */
7244 memmove(line + val_len, var_end, end - var_end + 1);
7245 memcpy(line, value, val_len);
7246 end += val_len - (var_end - line);
7247 line += val_len;
7248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007249 else {
7250 line++;
7251 }
7252 }
William Lallemandb2f07452015-05-12 14:27:13 +02007253
William Lallemandf9873ba2015-05-05 17:37:14 +02007254 if (dquote) {
7255 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7256 err_code |= ERR_ALERT | ERR_FATAL;
7257 }
7258
7259 if (squote) {
7260 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7261 err_code |= ERR_ALERT | ERR_FATAL;
7262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263
7264 /* empty line */
7265 if (!**args)
7266 continue;
7267
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007268 if (*line) {
7269 /* we had to stop due to too many args.
7270 * Let's terminate the string, print the offending part then cut the
7271 * last arg.
7272 */
7273 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7274 line++;
7275 *line = '\0';
7276
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007277 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007278 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007279 err_code |= ERR_ALERT | ERR_FATAL;
7280 args[arg] = line;
7281 }
7282
Willy Tarreau540abe42007-05-02 20:50:16 +02007283 /* zero out remaining args and ensure that at least one entry
7284 * is zeroed out.
7285 */
7286 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007287 args[arg] = line;
7288 }
7289
Willy Tarreau3842f002009-06-14 11:39:52 +02007290 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007291 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007292 char *tmp;
7293
Willy Tarreau3842f002009-06-14 11:39:52 +02007294 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007295 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007296 for (arg=0; *args[arg+1]; arg++)
7297 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007298 *tmp = '\0'; // fix the next arg to \0
7299 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007300 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007301 else if (!strcmp(args[0], "default")) {
7302 kwm = KWM_DEF;
7303 for (arg=0; *args[arg+1]; arg++)
7304 args[arg] = args[arg+1]; // shift args after inversion
7305 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007306
William Lallemand0f99e342011-10-12 17:50:54 +02007307 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7308 strcmp(args[0], "log") != 0) {
7309 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007310 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007311 }
7312
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007313 /* detect section start */
7314 list_for_each_entry(ics, &sections, list) {
7315 if (strcmp(args[0], ics->section_name) == 0) {
7316 cursection = ics->section_name;
7317 cs = ics;
7318 break;
7319 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007320 }
7321
Willy Tarreaubaaee002006-06-26 02:48:02 +02007322 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007323 if (cs)
7324 err_code |= cs->section_parser(file, linenum, args, kwm);
7325 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007326 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007327 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007328 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007329
7330 if (err_code & ERR_ABORT)
7331 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007332 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007333 free(cfg_scope);
7334 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007335 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007336 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007337 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007338 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007339}
7340
Willy Tarreau64ab6072014-09-16 12:17:36 +02007341/* This function propagates processes from frontend <from> to backend <to> so
7342 * that it is always guaranteed that a backend pointed to by a frontend is
7343 * bound to all of its processes. After that, if the target is a "listen"
7344 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007345 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007346 * checked first to ensure that <to> is already bound to all processes of
7347 * <from>, there is no risk of looping and we ensure to follow the shortest
7348 * path to the destination.
7349 *
7350 * It is possible to set <to> to NULL for the first call so that the function
7351 * takes care of visiting the initial frontend in <from>.
7352 *
7353 * It is important to note that the function relies on the fact that all names
7354 * have already been resolved.
7355 */
7356void propagate_processes(struct proxy *from, struct proxy *to)
7357{
7358 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007359
7360 if (to) {
7361 /* check whether we need to go down */
7362 if (from->bind_proc &&
7363 (from->bind_proc & to->bind_proc) == from->bind_proc)
7364 return;
7365
7366 if (!from->bind_proc && !to->bind_proc)
7367 return;
7368
7369 to->bind_proc = from->bind_proc ?
7370 (to->bind_proc | from->bind_proc) : 0;
7371
7372 /* now propagate down */
7373 from = to;
7374 }
7375
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007376 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007377 return;
7378
Willy Tarreauf6b70012014-12-18 14:00:43 +01007379 if (from->state == PR_STSTOPPED)
7380 return;
7381
Willy Tarreau64ab6072014-09-16 12:17:36 +02007382 /* default_backend */
7383 if (from->defbe.be)
7384 propagate_processes(from, from->defbe.be);
7385
7386 /* use_backend */
7387 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007388 if (rule->dynamic)
7389 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007390 to = rule->be.backend;
7391 propagate_processes(from, to);
7392 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007393}
7394
Willy Tarreaubb925012009-07-23 13:36:36 +02007395/*
7396 * Returns the error code, 0 if OK, or any combination of :
7397 * - ERR_ABORT: must abort ASAP
7398 * - ERR_FATAL: we can continue parsing but not start the service
7399 * - ERR_WARN: a warning has been emitted
7400 * - ERR_ALERT: an alert has been emitted
7401 * Only the two first ones can stop processing, the two others are just
7402 * indicators.
7403 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007404int check_config_validity()
7405{
7406 int cfgerr = 0;
7407 struct proxy *curproxy = NULL;
7408 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007409 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007410 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007411 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007412 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007413 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007414
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007415 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007416 /*
7417 * Now, check for the integrity of all that we have collected.
7418 */
7419
7420 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007421 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007422
Willy Tarreau193b8c62012-11-22 00:17:38 +01007423 if (!global.tune.max_http_hdr)
7424 global.tune.max_http_hdr = MAX_HTTP_HDR;
7425
7426 if (!global.tune.cookie_len)
7427 global.tune.cookie_len = CAPTURE_LEN;
7428
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007429 if (!global.tune.requri_len)
7430 global.tune.requri_len = REQURI_LEN;
7431
Emeric Brun96fd9262017-07-05 13:33:16 +02007432 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7433
Willy Tarreau193b8c62012-11-22 00:17:38 +01007434 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7435
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007436 /* allocate pool of resolution per resolvers */
7437 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7438 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7439 /* error message is already displayed by dns_alloc_resolution_pool() */
7440 err_code |= ERR_ALERT | ERR_ABORT;
7441 goto out;
7442 }
7443 }
7444
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007445 /* Post initialisation of the users and groups lists. */
7446 err_code = userlist_postinit();
7447 if (err_code != ERR_NONE)
7448 goto out;
7449
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007450 /* first, we will invert the proxy list order */
7451 curproxy = NULL;
7452 while (proxy) {
7453 struct proxy *next;
7454
7455 next = proxy->next;
7456 proxy->next = curproxy;
7457 curproxy = proxy;
7458 if (!next)
7459 break;
7460 proxy = next;
7461 }
7462
Willy Tarreau419ead82014-09-16 13:41:21 +02007463 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007464 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007465 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007466 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007467 struct act_rule *trule;
7468 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007469 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007470 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007471 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007472
Willy Tarreau050536d2012-10-04 08:47:34 +02007473 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007474 /* proxy ID not set, use automatic numbering with first
7475 * spare entry starting with next_pxid.
7476 */
7477 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7478 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7479 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007480 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007481 next_pxid++;
7482
Willy Tarreau55ea7572007-06-17 19:56:27 +02007483
Willy Tarreaubaaee002006-06-26 02:48:02 +02007484 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007485 /* ensure we don't keep listeners uselessly bound */
7486 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007487 free((void *)curproxy->table.peers.name);
7488 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007489 continue;
7490 }
7491
Willy Tarreau102df612014-05-07 23:56:38 +02007492 /* Check multi-process mode compatibility for the current proxy */
7493
7494 if (curproxy->bind_proc) {
7495 /* an explicit bind-process was specified, let's check how many
7496 * processes remain.
7497 */
David Carliere6c39412015-07-02 07:00:17 +00007498 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007499
7500 curproxy->bind_proc &= nbits(global.nbproc);
7501 if (!curproxy->bind_proc && nbproc == 1) {
7502 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);
7503 curproxy->bind_proc = 1;
7504 }
7505 else if (!curproxy->bind_proc && nbproc > 1) {
7506 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);
7507 curproxy->bind_proc = 0;
7508 }
7509 }
7510
Willy Tarreau3d209582014-05-09 17:06:11 +02007511 /* check and reduce the bind-proc of each listener */
7512 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7513 unsigned long mask;
7514
7515 if (!bind_conf->bind_proc)
7516 continue;
7517
7518 mask = nbits(global.nbproc);
7519 if (curproxy->bind_proc)
7520 mask &= curproxy->bind_proc;
7521 /* mask cannot be null here thanks to the previous checks */
7522
David Carliere6c39412015-07-02 07:00:17 +00007523 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007524 bind_conf->bind_proc &= mask;
7525
7526 if (!bind_conf->bind_proc && nbproc == 1) {
7527 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",
7528 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7529 bind_conf->bind_proc = mask & ~(mask - 1);
7530 }
7531 else if (!bind_conf->bind_proc && nbproc > 1) {
7532 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",
7533 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7534 bind_conf->bind_proc = 0;
7535 }
7536 }
7537
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 switch (curproxy->mode) {
7539 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007540 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007541 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007542 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007544 cfgerr++;
7545 }
7546
7547 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007548 Warning("config : servers will be ignored for %s '%s'.\n",
7549 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007550 break;
7551
7552 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007553 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007554 break;
7555
7556 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007557 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007558 break;
7559 }
7560
Willy Tarreauf3934b82015-08-11 11:36:45 +02007561 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7562 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7563 proxy_type_str(curproxy), curproxy->id);
7564 err_code |= ERR_WARN;
7565 }
7566
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007567 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007568 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007569 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007570 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 cfgerr++;
7573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007574#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007575 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007576 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7577 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007578 cfgerr++;
7579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007580#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007581 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007582 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7583 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007584 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007585 }
7586 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007587 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007588 /* If no LB algo is set in a backend, and we're not in
7589 * transparent mode, dispatch mode nor proxy mode, we
7590 * want to use balance roundrobin by default.
7591 */
7592 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7593 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007594 }
7595 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007596
Willy Tarreau1620ec32011-08-06 17:05:02 +02007597 if (curproxy->options & PR_O_DISPATCH)
7598 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7599 else if (curproxy->options & PR_O_HTTP_PROXY)
7600 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7601 else if (curproxy->options & PR_O_TRANSP)
7602 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007603
Willy Tarreau1620ec32011-08-06 17:05:02 +02007604 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7605 if (curproxy->options & PR_O_DISABLE404) {
7606 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7607 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7608 err_code |= ERR_WARN;
7609 curproxy->options &= ~PR_O_DISABLE404;
7610 }
7611 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7612 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7613 "send-state", proxy_type_str(curproxy), curproxy->id);
7614 err_code |= ERR_WARN;
7615 curproxy->options &= ~PR_O2_CHK_SNDST;
7616 }
Willy Tarreauef781042010-01-27 11:53:01 +01007617 }
7618
Simon Horman98637e52014-06-20 12:30:16 +09007619 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7620 if (!global.external_check) {
7621 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7622 curproxy->id, "option external-check");
7623 cfgerr++;
7624 }
7625 if (!curproxy->check_command) {
7626 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7627 curproxy->id, "option external-check");
7628 cfgerr++;
7629 }
7630 }
7631
Simon Horman64e34162015-02-06 11:11:57 +09007632 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007633 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7634 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007635 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7636 "'email-alert myhostname', or 'email-alert to' "
7637 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007638 "to be present).\n",
7639 proxy_type_str(curproxy), curproxy->id);
7640 err_code |= ERR_WARN;
7641 free_email_alert(curproxy);
7642 }
7643 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007644 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007645 }
7646
Simon Horman98637e52014-06-20 12:30:16 +09007647 if (curproxy->check_command) {
7648 int clear = 0;
7649 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7650 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7651 "external-check command", proxy_type_str(curproxy), curproxy->id);
7652 err_code |= ERR_WARN;
7653 clear = 1;
7654 }
7655 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007656 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007657 curproxy->id, "external-check command");
7658 cfgerr++;
7659 }
7660 if (clear) {
7661 free(curproxy->check_command);
7662 curproxy->check_command = NULL;
7663 }
7664 }
7665
7666 if (curproxy->check_path) {
7667 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7668 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7669 "external-check path", proxy_type_str(curproxy), curproxy->id);
7670 err_code |= ERR_WARN;
7671 free(curproxy->check_path);
7672 curproxy->check_path = NULL;
7673 }
7674 }
7675
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007676 /* if a default backend was specified, let's find it */
7677 if (curproxy->defbe.name) {
7678 struct proxy *target;
7679
Willy Tarreauafb39922015-05-26 12:04:09 +02007680 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007681 if (!target) {
7682 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7683 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007684 cfgerr++;
7685 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007686 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7687 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007688 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007689 } else if (target->mode != curproxy->mode &&
7690 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7691
7692 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7693 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7694 curproxy->conf.file, curproxy->conf.line,
7695 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7696 target->conf.file, target->conf.line);
7697 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007698 } else {
7699 free(curproxy->defbe.name);
7700 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007701 /* Update tot_fe_maxconn for a further fullconn's computation */
7702 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007703 /* Emit a warning if this proxy also has some servers */
7704 if (curproxy->srv) {
7705 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7706 curproxy->id);
7707 err_code |= ERR_WARN;
7708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007709 }
7710 }
7711
Emeric Brun3f783572017-01-12 11:21:28 +01007712 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7713 /* Case of listen without default backend
7714 * The curproxy will be its own default backend
7715 * so we update tot_fe_maxconn for a further
7716 * fullconn's computation */
7717 curproxy->tot_fe_maxconn += curproxy->maxconn;
7718 }
7719
Willy Tarreau55ea7572007-06-17 19:56:27 +02007720 /* find the target proxy for 'use_backend' rules */
7721 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007722 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007723 struct logformat_node *node;
7724 char *pxname;
7725
7726 /* Try to parse the string as a log format expression. If the result
7727 * of the parsing is only one entry containing a simple string, then
7728 * it's a standard string corresponding to a static rule, thus the
7729 * parsing is cancelled and be.name is restored to be resolved.
7730 */
7731 pxname = rule->be.name;
7732 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007733 curproxy->conf.args.ctx = ARGC_UBK;
7734 curproxy->conf.args.file = rule->file;
7735 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007736 err = NULL;
7737 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7738 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7739 rule->file, rule->line, pxname, err);
7740 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007741 cfgerr++;
7742 continue;
7743 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007744 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7745
7746 if (!LIST_ISEMPTY(&rule->be.expr)) {
7747 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7748 rule->dynamic = 1;
7749 free(pxname);
7750 continue;
7751 }
7752 /* simple string: free the expression and fall back to static rule */
7753 free(node->arg);
7754 free(node);
7755 }
7756
7757 rule->dynamic = 0;
7758 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007759
Willy Tarreauafb39922015-05-26 12:04:09 +02007760 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007761 if (!target) {
7762 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7763 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007764 cfgerr++;
7765 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007766 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7767 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007768 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007769 } else if (target->mode != curproxy->mode &&
7770 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7771
7772 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7773 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7774 curproxy->conf.file, curproxy->conf.line,
7775 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7776 target->conf.file, target->conf.line);
7777 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007778 } else {
7779 free((void *)rule->be.name);
7780 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007781 /* For each target of switching rules, we update
7782 * their tot_fe_maxconn, except if a previous rule point
7783 * on the same backend or on the default backend */
7784 if (rule->be.backend != curproxy->defbe.be) {
7785 struct switching_rule *swrule;
7786
7787 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7788 if (rule == swrule) {
7789 target->tot_fe_maxconn += curproxy->maxconn;
7790 break;
7791 }
7792 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7793 /* there is multiple ref of this backend */
7794 break;
7795 }
7796 }
7797 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007798 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007799 }
7800
Willy Tarreau64ab6072014-09-16 12:17:36 +02007801 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007802 list_for_each_entry(srule, &curproxy->server_rules, list) {
7803 struct server *target = findserver(curproxy, srule->srv.name);
7804
7805 if (!target) {
7806 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7807 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7808 cfgerr++;
7809 continue;
7810 }
7811 free((void *)srule->srv.name);
7812 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007813 }
7814
Emeric Brunb982a3d2010-01-04 15:45:53 +01007815 /* find the target table for 'stick' rules */
7816 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7817 struct proxy *target;
7818
Emeric Brun1d33b292010-01-04 15:47:17 +01007819 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7820 if (mrule->flags & STK_IS_STORE)
7821 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7822
Emeric Brunb982a3d2010-01-04 15:45:53 +01007823 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007824 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007825 else
7826 target = curproxy;
7827
7828 if (!target) {
7829 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7830 curproxy->id, mrule->table.name);
7831 cfgerr++;
7832 }
7833 else if (target->table.size == 0) {
7834 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7835 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7836 cfgerr++;
7837 }
Willy Tarreau12785782012-04-27 21:37:17 +02007838 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7839 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7841 cfgerr++;
7842 }
7843 else {
7844 free((void *)mrule->table.name);
7845 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007846 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007847 }
7848 }
7849
7850 /* find the target table for 'store response' rules */
7851 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7852 struct proxy *target;
7853
Emeric Brun1d33b292010-01-04 15:47:17 +01007854 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7855
Emeric Brunb982a3d2010-01-04 15:45:53 +01007856 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007857 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007858 else
7859 target = curproxy;
7860
7861 if (!target) {
7862 Alert("Proxy '%s': unable to find store table '%s'.\n",
7863 curproxy->id, mrule->table.name);
7864 cfgerr++;
7865 }
7866 else if (target->table.size == 0) {
7867 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7868 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7869 cfgerr++;
7870 }
Willy Tarreau12785782012-04-27 21:37:17 +02007871 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7872 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007873 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7874 cfgerr++;
7875 }
7876 else {
7877 free((void *)mrule->table.name);
7878 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007879 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007880 }
7881 }
7882
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007883 /* find the target table for 'tcp-request' layer 4 rules */
7884 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7885 struct proxy *target;
7886
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007887 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007888 continue;
7889
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 if (trule->arg.trk_ctr.table.n)
7891 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007892 else
7893 target = curproxy;
7894
7895 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007896 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007898 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007899 cfgerr++;
7900 }
7901 else if (target->table.size == 0) {
7902 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007903 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007904 cfgerr++;
7905 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007906 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007907 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007908 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007909 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007910 cfgerr++;
7911 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007912 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007913 free(trule->arg.trk_ctr.table.n);
7914 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007915 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007916 * to pass a list of counters to track and allocate them right here using
7917 * stktable_alloc_data_type().
7918 */
7919 }
7920 }
7921
Willy Tarreau620408f2016-10-21 16:37:51 +02007922 /* find the target table for 'tcp-request' layer 5 rules */
7923 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7924 struct proxy *target;
7925
7926 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7927 continue;
7928
7929 if (trule->arg.trk_ctr.table.n)
7930 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7931 else
7932 target = curproxy;
7933
7934 if (!target) {
7935 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7936 curproxy->id, trule->arg.trk_ctr.table.n,
7937 tcp_trk_idx(trule->action));
7938 cfgerr++;
7939 }
7940 else if (target->table.size == 0) {
7941 Alert("Proxy '%s': table '%s' used but not configured.\n",
7942 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7943 cfgerr++;
7944 }
7945 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7946 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7947 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7948 tcp_trk_idx(trule->action));
7949 cfgerr++;
7950 }
7951 else {
7952 free(trule->arg.trk_ctr.table.n);
7953 trule->arg.trk_ctr.table.t = &target->table;
7954 /* Note: if we decide to enhance the track-sc syntax, we may be able
7955 * to pass a list of counters to track and allocate them right here using
7956 * stktable_alloc_data_type().
7957 */
7958 }
7959 }
7960
Willy Tarreaud1f96522010-08-03 19:34:32 +02007961 /* find the target table for 'tcp-request' layer 6 rules */
7962 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7963 struct proxy *target;
7964
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007965 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007966 continue;
7967
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007968 if (trule->arg.trk_ctr.table.n)
7969 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007970 else
7971 target = curproxy;
7972
7973 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007974 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007975 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007976 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007977 cfgerr++;
7978 }
7979 else if (target->table.size == 0) {
7980 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007981 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007982 cfgerr++;
7983 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007984 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007985 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007986 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007987 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007988 cfgerr++;
7989 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007990 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007991 free(trule->arg.trk_ctr.table.n);
7992 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007993 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007994 * to pass a list of counters to track and allocate them right here using
7995 * stktable_alloc_data_type().
7996 */
7997 }
7998 }
7999
Baptiste Assmanne9544932015-11-03 23:31:35 +01008000 /* parse http-request capture rules to ensure id really exists */
8001 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8002 if (hrqrule->action != ACT_CUSTOM ||
8003 hrqrule->action_ptr != http_action_req_capture_by_id)
8004 continue;
8005
8006 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8007 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8008 curproxy->id, hrqrule->arg.capid.idx);
8009 cfgerr++;
8010 }
8011 }
8012
8013 /* parse http-response capture rules to ensure id really exists */
8014 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8015 if (hrqrule->action != ACT_CUSTOM ||
8016 hrqrule->action_ptr != http_action_res_capture_by_id)
8017 continue;
8018
8019 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8020 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8021 curproxy->id, hrqrule->arg.capid.idx);
8022 cfgerr++;
8023 }
8024 }
8025
Willy Tarreau09448f72014-06-25 18:12:15 +02008026 /* find the target table for 'http-request' layer 7 rules */
8027 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8028 struct proxy *target;
8029
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008030 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008031 continue;
8032
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008033 if (hrqrule->arg.trk_ctr.table.n)
8034 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008035 else
8036 target = curproxy;
8037
8038 if (!target) {
8039 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008040 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008041 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008042 cfgerr++;
8043 }
8044 else if (target->table.size == 0) {
8045 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008046 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008047 cfgerr++;
8048 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008049 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008050 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008051 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008052 http_trk_idx(hrqrule->action));
8053 cfgerr++;
8054 }
8055 else {
8056 free(hrqrule->arg.trk_ctr.table.n);
8057 hrqrule->arg.trk_ctr.table.t = &target->table;
8058 /* Note: if we decide to enhance the track-sc syntax, we may be able
8059 * to pass a list of counters to track and allocate them right here using
8060 * stktable_alloc_data_type().
8061 */
8062 }
8063 }
8064
8065 /* find the target table for 'http-response' layer 7 rules */
8066 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8067 struct proxy *target;
8068
8069 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8070 continue;
8071
8072 if (hrqrule->arg.trk_ctr.table.n)
8073 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8074 else
8075 target = curproxy;
8076
8077 if (!target) {
8078 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8079 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8080 http_trk_idx(hrqrule->action));
8081 cfgerr++;
8082 }
8083 else if (target->table.size == 0) {
8084 Alert("Proxy '%s': table '%s' used but not configured.\n",
8085 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8086 cfgerr++;
8087 }
8088 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8089 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8090 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8091 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008092 cfgerr++;
8093 }
8094 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008095 free(hrqrule->arg.trk_ctr.table.n);
8096 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008097 /* Note: if we decide to enhance the track-sc syntax, we may be able
8098 * to pass a list of counters to track and allocate them right here using
8099 * stktable_alloc_data_type().
8100 */
8101 }
8102 }
8103
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008104 /* move any "block" rules at the beginning of the http-request rules */
8105 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8106 /* insert block_rules into http_req_rules at the beginning */
8107 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8108 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8109 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8110 curproxy->http_req_rules.n = curproxy->block_rules.n;
8111 LIST_INIT(&curproxy->block_rules);
8112 }
8113
Emeric Brun32da3c42010-09-23 18:39:19 +02008114 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008115 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008116
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008117 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008118 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8119 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008120 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008121 break;
8122 }
8123 }
8124
8125 if (!curpeers) {
8126 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8127 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008128 free((void *)curproxy->table.peers.name);
8129 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008130 cfgerr++;
8131 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008132 else if (curpeers->state == PR_STSTOPPED) {
8133 /* silently disable this peers section */
8134 curproxy->table.peers.p = NULL;
8135 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008136 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008137 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8138 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008139 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008140 cfgerr++;
8141 }
8142 }
8143
Simon Horman9dc49962015-01-30 11:22:59 +09008144
8145 if (curproxy->email_alert.mailers.name) {
8146 struct mailers *curmailers = mailers;
8147
8148 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8149 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8150 free(curproxy->email_alert.mailers.name);
8151 curproxy->email_alert.mailers.m = curmailers;
8152 curmailers->users++;
8153 break;
8154 }
8155 }
8156
8157 if (!curmailers) {
8158 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8159 curproxy->id, curproxy->email_alert.mailers.name);
8160 free_email_alert(curproxy);
8161 cfgerr++;
8162 }
8163 }
8164
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008165 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008166 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008167 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8168 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8169 "proxy", curproxy->id);
8170 cfgerr++;
8171 goto out_uri_auth_compat;
8172 }
8173
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008174 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008175 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008176 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008177 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008178
Willy Tarreau95fa4692010-02-01 13:05:50 +01008179 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8180 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008181
8182 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008183 uri_auth_compat_req[i++] = "realm";
8184 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8185 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008186
Willy Tarreau95fa4692010-02-01 13:05:50 +01008187 uri_auth_compat_req[i++] = "unless";
8188 uri_auth_compat_req[i++] = "{";
8189 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8190 uri_auth_compat_req[i++] = "}";
8191 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008192
Willy Tarreauff011f22011-01-06 17:51:27 +01008193 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8194 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008195 cfgerr++;
8196 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008197 }
8198
Willy Tarreauff011f22011-01-06 17:51:27 +01008199 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008200
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008201 if (curproxy->uri_auth->auth_realm) {
8202 free(curproxy->uri_auth->auth_realm);
8203 curproxy->uri_auth->auth_realm = NULL;
8204 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008205
8206 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008207 }
8208out_uri_auth_compat:
8209
Dragan Dosen43885c72015-10-01 13:18:13 +02008210 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008211 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008212 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8213 if (!curproxy->conf.logformat_sd_string) {
8214 /* set the default logformat_sd_string */
8215 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8216 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008217 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008218 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008219 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008220
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008221 /* compile the log format */
8222 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008223 if (curproxy->conf.logformat_string != default_http_log_format &&
8224 curproxy->conf.logformat_string != default_tcp_log_format &&
8225 curproxy->conf.logformat_string != clf_http_log_format)
8226 free(curproxy->conf.logformat_string);
8227 curproxy->conf.logformat_string = NULL;
8228 free(curproxy->conf.lfs_file);
8229 curproxy->conf.lfs_file = NULL;
8230 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008231
8232 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8233 free(curproxy->conf.logformat_sd_string);
8234 curproxy->conf.logformat_sd_string = NULL;
8235 free(curproxy->conf.lfsd_file);
8236 curproxy->conf.lfsd_file = NULL;
8237 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008238 }
8239
Willy Tarreau62a61232013-04-12 18:13:46 +02008240 if (curproxy->conf.logformat_string) {
8241 curproxy->conf.args.ctx = ARGC_LOG;
8242 curproxy->conf.args.file = curproxy->conf.lfs_file;
8243 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008244 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008245 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008246 SMP_VAL_FE_LOG_END, &err)) {
8247 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8248 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8249 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008250 cfgerr++;
8251 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008252 curproxy->conf.args.file = NULL;
8253 curproxy->conf.args.line = 0;
8254 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008255
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008256 if (curproxy->conf.logformat_sd_string) {
8257 curproxy->conf.args.ctx = ARGC_LOGSD;
8258 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8259 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008260 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008261 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 +01008262 SMP_VAL_FE_LOG_END, &err)) {
8263 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8264 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8265 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008266 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008267 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8268 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8269 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8270 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008271 cfgerr++;
8272 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008273 curproxy->conf.args.file = NULL;
8274 curproxy->conf.args.line = 0;
8275 }
8276
Willy Tarreau62a61232013-04-12 18:13:46 +02008277 if (curproxy->conf.uniqueid_format_string) {
8278 curproxy->conf.args.ctx = ARGC_UIF;
8279 curproxy->conf.args.file = curproxy->conf.uif_file;
8280 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008281 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008282 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 +01008283 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8284 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8285 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8286 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008287 cfgerr++;
8288 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008289 curproxy->conf.args.file = NULL;
8290 curproxy->conf.args.line = 0;
8291 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008292
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008293 /* only now we can check if some args remain unresolved.
8294 * This must be done after the users and groups resolution.
8295 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008296 cfgerr += smp_resolve_args(curproxy);
8297 if (!cfgerr)
8298 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008299
Willy Tarreau2738a142006-07-08 17:28:09 +02008300 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008301 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008302 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008303 (!curproxy->timeout.connect ||
8304 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008305 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008306 " | While not properly invalid, you will certainly encounter various problems\n"
8307 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008308 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008309 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008310 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008311 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008312
Willy Tarreau1fa31262007-12-03 00:36:16 +01008313 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8314 * We must still support older configurations, so let's find out whether those
8315 * parameters have been set or must be copied from contimeouts.
8316 */
8317 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008318 if (!curproxy->timeout.tarpit ||
8319 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008320 /* tarpit timeout not set. We search in the following order:
8321 * default.tarpit, curr.connect, default.connect.
8322 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008323 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008324 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008325 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008326 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008327 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008328 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008329 }
8330 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008331 (!curproxy->timeout.queue ||
8332 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008333 /* queue timeout not set. We search in the following order:
8334 * default.queue, curr.connect, default.connect.
8335 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008336 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008337 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008338 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008339 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008340 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008341 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008342 }
8343 }
8344
Willy Tarreau1620ec32011-08-06 17:05:02 +02008345 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008346 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008347 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008348 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008349 }
8350
Willy Tarreau215663d2014-06-13 18:30:23 +02008351 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8352 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8353 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8354 proxy_type_str(curproxy), curproxy->id);
8355 err_code |= ERR_WARN;
8356 }
8357
Willy Tarreau193b8c62012-11-22 00:17:38 +01008358 /* ensure that cookie capture length is not too large */
8359 if (curproxy->capture_len >= global.tune.cookie_len) {
8360 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8361 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8362 err_code |= ERR_WARN;
8363 curproxy->capture_len = global.tune.cookie_len - 1;
8364 }
8365
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008366 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008367 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008368 curproxy->req_cap_pool = create_pool("ptrcap",
8369 curproxy->nb_req_cap * sizeof(char *),
8370 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008371 }
8372
8373 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008374 curproxy->rsp_cap_pool = create_pool("ptrcap",
8375 curproxy->nb_rsp_cap * sizeof(char *),
8376 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008377 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008378
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008379 switch (curproxy->load_server_state_from_file) {
8380 case PR_SRV_STATE_FILE_UNSPEC:
8381 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8382 break;
8383 case PR_SRV_STATE_FILE_GLOBAL:
8384 if (!global.server_state_file) {
8385 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",
8386 curproxy->id);
8387 err_code |= ERR_WARN;
8388 }
8389 break;
8390 }
8391
Willy Tarreaubaaee002006-06-26 02:48:02 +02008392 /* first, we will invert the servers list order */
8393 newsrv = NULL;
8394 while (curproxy->srv) {
8395 struct server *next;
8396
8397 next = curproxy->srv->next;
8398 curproxy->srv->next = newsrv;
8399 newsrv = curproxy->srv;
8400 if (!next)
8401 break;
8402 curproxy->srv = next;
8403 }
8404
Willy Tarreau17edc812014-01-03 12:14:34 +01008405 /* Check that no server name conflicts. This causes trouble in the stats.
8406 * We only emit a warning for the first conflict affecting each server,
8407 * in order to avoid combinatory explosion if all servers have the same
8408 * name. We do that only for servers which do not have an explicit ID,
8409 * because these IDs were made also for distinguishing them and we don't
8410 * want to annoy people who correctly manage them.
8411 */
8412 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8413 struct server *other_srv;
8414
8415 if (newsrv->puid)
8416 continue;
8417
8418 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8419 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8420 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8421 newsrv->conf.file, newsrv->conf.line,
8422 proxy_type_str(curproxy), curproxy->id,
8423 newsrv->id, other_srv->conf.line);
8424 break;
8425 }
8426 }
8427 }
8428
Willy Tarreaudd701652010-05-25 23:03:02 +02008429 /* assign automatic UIDs to servers which don't have one yet */
8430 next_id = 1;
8431 newsrv = curproxy->srv;
8432 while (newsrv != NULL) {
8433 if (!newsrv->puid) {
8434 /* server ID not set, use automatic numbering with first
8435 * spare entry starting with next_svid.
8436 */
8437 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8438 newsrv->conf.id.key = newsrv->puid = next_id;
8439 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8440 }
8441 next_id++;
8442 newsrv = newsrv->next;
8443 }
8444
Willy Tarreau20697042007-11-15 23:26:18 +01008445 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008446 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008447
Willy Tarreau62c3be22012-01-20 13:12:32 +01008448 /*
8449 * If this server supports a maxconn parameter, it needs a dedicated
8450 * tasks to fill the emptied slots when a connection leaves.
8451 * Also, resolve deferred tracking dependency if needed.
8452 */
8453 newsrv = curproxy->srv;
8454 while (newsrv != NULL) {
8455 if (newsrv->minconn > newsrv->maxconn) {
8456 /* Only 'minconn' was specified, or it was higher than or equal
8457 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8458 * this will avoid further useless expensive computations.
8459 */
8460 newsrv->maxconn = newsrv->minconn;
8461 } else if (newsrv->maxconn && !newsrv->minconn) {
8462 /* minconn was not specified, so we set it to maxconn */
8463 newsrv->minconn = newsrv->maxconn;
8464 }
8465
Willy Tarreau17d45382016-12-22 21:16:08 +01008466 /* this will also properly set the transport layer for prod and checks */
8467 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8468 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8469 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8470 }
Emeric Brun94324a42012-10-11 14:00:19 +02008471
Willy Tarreau2f075e92013-12-03 11:11:34 +01008472 /* set the check type on the server */
8473 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8474
Willy Tarreau62c3be22012-01-20 13:12:32 +01008475 if (newsrv->trackit) {
8476 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008477 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008478 char *pname, *sname;
8479
8480 pname = newsrv->trackit;
8481 sname = strrchr(pname, '/');
8482
8483 if (sname)
8484 *sname++ = '\0';
8485 else {
8486 sname = pname;
8487 pname = NULL;
8488 }
8489
8490 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008491 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008492 if (!px) {
8493 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8494 proxy_type_str(curproxy), curproxy->id,
8495 newsrv->id, pname);
8496 cfgerr++;
8497 goto next_srv;
8498 }
8499 } else
8500 px = curproxy;
8501
8502 srv = findserver(px, sname);
8503 if (!srv) {
8504 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8505 proxy_type_str(curproxy), curproxy->id,
8506 newsrv->id, sname);
8507 cfgerr++;
8508 goto next_srv;
8509 }
8510
Willy Tarreau32091232014-05-16 13:52:00 +02008511 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8512 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8513 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008515 "tracking as it does not have any check nor agent enabled.\n",
8516 proxy_type_str(curproxy), curproxy->id,
8517 newsrv->id, px->id, srv->id);
8518 cfgerr++;
8519 goto next_srv;
8520 }
8521
8522 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8523
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008524 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008525 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8526 "belongs to a tracking chain looping back to %s/%s.\n",
8527 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008528 newsrv->id, px->id, srv->id, px->id,
8529 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008530 cfgerr++;
8531 goto next_srv;
8532 }
8533
8534 if (curproxy != px &&
8535 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8536 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8537 "tracking: disable-on-404 option inconsistency.\n",
8538 proxy_type_str(curproxy), curproxy->id,
8539 newsrv->id, px->id, srv->id);
8540 cfgerr++;
8541 goto next_srv;
8542 }
8543
Willy Tarreau62c3be22012-01-20 13:12:32 +01008544 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008545 newsrv->tracknext = srv->trackers;
8546 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008547
8548 free(newsrv->trackit);
8549 newsrv->trackit = NULL;
8550 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008551
8552 /*
8553 * resolve server's resolvers name and update the resolvers pointer
8554 * accordingly
8555 */
8556 if (newsrv->resolvers_id) {
8557 struct dns_resolvers *curr_resolvers;
8558 int found;
8559
8560 found = 0;
8561 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8562 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8563 found = 1;
8564 break;
8565 }
8566 }
8567
8568 if (!found) {
8569 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8570 proxy_type_str(curproxy), curproxy->id,
8571 newsrv->id, newsrv->resolvers_id);
8572 cfgerr++;
8573 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008574 if (newsrv->srvrq) {
8575 if (!newsrv->srvrq->resolvers) {
8576 newsrv->srvrq->resolvers = curr_resolvers;
8577 if (dns_link_resolution(newsrv->srvrq,
8578 OBJ_TYPE_SRVRQ, NULL) != 0) {
8579 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8580 proxy_type_str(curproxy), curproxy->id,
8581 newsrv->id);
8582 cfgerr++;
8583 }
8584 }
8585
8586 }
8587 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008588 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008589 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8590 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8591 proxy_type_str(curproxy), curproxy->id,
8592 newsrv->id);
8593 cfgerr++;
8594 }
8595 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008596 }
8597 }
8598 else {
8599 /* if no resolvers section associated to this server
8600 * we can clean up the associated resolution structure
8601 */
8602 if (newsrv->resolution) {
8603 free(newsrv->resolution->hostname_dn);
8604 newsrv->resolution->hostname_dn = NULL;
8605 free(newsrv->resolution);
8606 newsrv->resolution = NULL;
8607 }
8608 }
8609
Willy Tarreau62c3be22012-01-20 13:12:32 +01008610 next_srv:
8611 newsrv = newsrv->next;
8612 }
8613
Olivier Houchard4e694042017-03-14 20:01:29 +01008614 /*
8615 * Try to generate dynamic cookies for servers now.
8616 * It couldn't be done earlier, since at the time we parsed
8617 * the server line, we may not have known yet that we
8618 * should use dynamic cookies, or the secret key may not
8619 * have been provided yet.
8620 */
8621 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8622 newsrv = curproxy->srv;
8623 while (newsrv != NULL) {
8624 srv_set_dyncookie(newsrv);
8625 newsrv = newsrv->next;
8626 }
8627
8628 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008629 /* We have to initialize the server lookup mechanism depending
8630 * on what LB algorithm was choosen.
8631 */
8632
8633 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8634 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8635 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008636 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8637 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8638 init_server_map(curproxy);
8639 } else {
8640 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8641 fwrr_init_server_groups(curproxy);
8642 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008643 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008644
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008645 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008646 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8647 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8648 fwlc_init_server_tree(curproxy);
8649 } else {
8650 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8651 fas_init_server_tree(curproxy);
8652 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008653 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008654
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008655 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008656 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8657 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8658 chash_init_server_tree(curproxy);
8659 } else {
8660 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8661 init_server_map(curproxy);
8662 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008663 break;
8664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008665
8666 if (curproxy->options & PR_O_LOGASAP)
8667 curproxy->to_log &= ~LW_BYTES;
8668
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008669 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008670 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8671 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008672 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8673 proxy_type_str(curproxy), curproxy->id);
8674 err_code |= ERR_WARN;
8675 }
8676
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008677 if (curproxy->mode != PR_MODE_HTTP) {
8678 int optnum;
8679
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008680 if (curproxy->uri_auth) {
8681 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8682 proxy_type_str(curproxy), curproxy->id);
8683 err_code |= ERR_WARN;
8684 curproxy->uri_auth = NULL;
8685 }
8686
Willy Tarreaude7dc882017-03-10 11:49:21 +01008687 if (curproxy->capture_name) {
8688 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8689 proxy_type_str(curproxy), curproxy->id);
8690 err_code |= ERR_WARN;
8691 }
8692
8693 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8694 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8695 proxy_type_str(curproxy), curproxy->id);
8696 err_code |= ERR_WARN;
8697 }
8698
8699 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8700 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8701 proxy_type_str(curproxy), curproxy->id);
8702 err_code |= ERR_WARN;
8703 }
8704
8705 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8706 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8707 proxy_type_str(curproxy), curproxy->id);
8708 err_code |= ERR_WARN;
8709 }
8710
8711 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8712 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8713 proxy_type_str(curproxy), curproxy->id);
8714 err_code |= ERR_WARN;
8715 }
8716
Willy Tarreau87cf5142011-08-19 22:57:24 +02008717 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008718 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8719 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8720 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008721 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008722 }
8723
8724 if (curproxy->options & PR_O_ORGTO) {
8725 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8726 "originalto", proxy_type_str(curproxy), curproxy->id);
8727 err_code |= ERR_WARN;
8728 curproxy->options &= ~PR_O_ORGTO;
8729 }
8730
8731 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8732 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8733 (curproxy->cap & cfg_opts[optnum].cap) &&
8734 (curproxy->options & cfg_opts[optnum].val)) {
8735 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8736 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8737 err_code |= ERR_WARN;
8738 curproxy->options &= ~cfg_opts[optnum].val;
8739 }
8740 }
8741
8742 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8743 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8744 (curproxy->cap & cfg_opts2[optnum].cap) &&
8745 (curproxy->options2 & cfg_opts2[optnum].val)) {
8746 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8747 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8748 err_code |= ERR_WARN;
8749 curproxy->options2 &= ~cfg_opts2[optnum].val;
8750 }
8751 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008752
Willy Tarreau29fbe512015-08-20 19:35:14 +02008753#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008754 if (curproxy->conn_src.bind_hdr_occ) {
8755 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008756 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008757 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008758 err_code |= ERR_WARN;
8759 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008760#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008761 }
8762
Willy Tarreaubaaee002006-06-26 02:48:02 +02008763 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008764 * ensure that we're not cross-dressing a TCP server into HTTP.
8765 */
8766 newsrv = curproxy->srv;
8767 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008768 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008769 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8770 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008771 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008772 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008773
Willy Tarreau0cec3312011-10-31 13:49:26 +01008774 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8775 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8776 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8777 err_code |= ERR_WARN;
8778 }
8779
Willy Tarreauc93cd162014-05-13 15:54:22 +02008780 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008781 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8782 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8783 err_code |= ERR_WARN;
8784 }
8785
Willy Tarreau29fbe512015-08-20 19:35:14 +02008786#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008787 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8788 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008789 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 +01008790 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008791 err_code |= ERR_WARN;
8792 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008793#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008794
8795 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8796 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8797 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8798 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8799 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8800 Warning("config : %s '%s' : connections to server '%s' use the client's IP address as the source while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'usesrc' and to use the 'forwardfor' option instead.\n",
8801 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8802 err_code |= ERR_WARN;
8803 }
8804
8805
8806 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8807 Warning("config : %s '%s' : connections to server '%s' will have a PROXY protocol header announcing the first client's IP address while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'send-proxy' and to use the 'forwardfor' option instead.\n",
8808 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8809 err_code |= ERR_WARN;
8810 }
8811 }
8812
Willy Tarreau21d2af32008-02-14 20:25:24 +01008813 newsrv = newsrv->next;
8814 }
8815
Willy Tarreaue42bd962014-09-16 16:21:19 +02008816 /* check if we have a frontend with "tcp-request content" looking at L7
8817 * with no inspect-delay
8818 */
8819 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8820 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008821 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008822 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008823 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008824 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008825 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008826 break;
8827 }
8828
8829 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8830 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8831 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8832 " This means that these rules will randomly find their contents. This can be fixed by"
8833 " setting the tcp-request inspect-delay.\n",
8834 proxy_type_str(curproxy), curproxy->id);
8835 err_code |= ERR_WARN;
8836 }
8837 }
8838
Christopher Fauletd7c91962015-04-30 11:48:27 +02008839 /* Check filter configuration, if any */
8840 cfgerr += flt_check(curproxy);
8841
Willy Tarreauc1a21672009-08-16 22:37:44 +02008842 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008843 if (!curproxy->accept)
8844 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008845
Willy Tarreauc1a21672009-08-16 22:37:44 +02008846 if (curproxy->tcp_req.inspect_delay ||
8847 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008848 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008849
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008850 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008851 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008852 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008853 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008854
8855 /* both TCP and HTTP must check switching rules */
8856 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008857
8858 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008859 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008860 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8861 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008862 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008863 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8864 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008865 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008866 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008867 }
8868
8869 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008870 if (curproxy->tcp_req.inspect_delay ||
8871 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8872 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8873
Emeric Brun97679e72010-09-23 17:56:44 +02008874 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8875 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8876
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008877 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008878 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008879 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008880 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008881
8882 /* If the backend does requires RDP cookie persistence, we have to
8883 * enable the corresponding analyser.
8884 */
8885 if (curproxy->options2 & PR_O2_RDPC_PRST)
8886 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008887
8888 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008889 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008890 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8891 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008892 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008893 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8894 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008895 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008896 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008897 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008898 }
8899
8900 /***********************************************************/
8901 /* At this point, target names have already been resolved. */
8902 /***********************************************************/
8903
8904 /* Check multi-process mode compatibility */
8905
8906 if (global.nbproc > 1 && global.stats_fe) {
8907 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8908 unsigned long mask;
8909
8910 mask = nbits(global.nbproc);
8911 if (global.stats_fe->bind_proc)
8912 mask &= global.stats_fe->bind_proc;
8913
8914 if (bind_conf->bind_proc)
8915 mask &= bind_conf->bind_proc;
8916
8917 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008918 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008919 break;
8920 }
8921 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8922 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");
8923 }
8924 }
8925
8926 /* Make each frontend inherit bind-process from its listeners when not specified. */
8927 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8928 if (curproxy->bind_proc)
8929 continue;
8930
8931 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8932 unsigned long mask;
8933
Willy Tarreaue428b082015-05-04 21:57:58 +02008934 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008935 curproxy->bind_proc |= mask;
8936 }
8937
8938 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008939 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008940 }
8941
8942 if (global.stats_fe) {
8943 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8944 unsigned long mask;
8945
Cyril Bonté06181952016-02-24 00:14:54 +01008946 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008947 global.stats_fe->bind_proc |= mask;
8948 }
8949 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008950 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008951 }
8952
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008953 /* propagate bindings from frontends to backends. Don't do it if there
8954 * are any fatal errors as we must not call it with unresolved proxies.
8955 */
8956 if (!cfgerr) {
8957 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8958 if (curproxy->cap & PR_CAP_FE)
8959 propagate_processes(curproxy, NULL);
8960 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008961 }
8962
8963 /* Bind each unbound backend to all processes when not specified. */
8964 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8965 if (curproxy->bind_proc)
8966 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008967 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008968 }
8969
8970 /*******************************************************/
8971 /* At this step, all proxies have a non-null bind_proc */
8972 /*******************************************************/
8973
8974 /* perform the final checks before creating tasks */
8975
8976 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8977 struct listener *listener;
8978 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008979
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008980 /* Configure SSL for each bind line.
8981 * Note: if configuration fails at some point, the ->ctx member
8982 * remains NULL so that listeners can later detach.
8983 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008984 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008985 if (bind_conf->xprt->prepare_bind_conf &&
8986 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008987 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008988 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008989
Willy Tarreaue6b98942007-10-29 01:09:36 +01008990 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008991 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008992 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008993 int nbproc;
8994
8995 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008996 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008997 nbits(global.nbproc));
8998
8999 if (!nbproc) /* no intersection between listener and frontend */
9000 nbproc = 1;
9001
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009002 if (!listener->luid) {
9003 /* listener ID not set, use automatic numbering with first
9004 * spare entry starting with next_luid.
9005 */
9006 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
9007 listener->conf.id.key = listener->luid = next_id;
9008 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009009 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01009010 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009011
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009012 /* enable separate counters */
9013 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01009014 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009015 if (!listener->name)
9016 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009017 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009018
Willy Tarreaue6b98942007-10-29 01:09:36 +01009019 if (curproxy->options & PR_O_TCP_NOLING)
9020 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009021 if (!listener->maxconn)
9022 listener->maxconn = curproxy->maxconn;
9023 if (!listener->backlog)
9024 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009025 if (!listener->maxaccept)
9026 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9027
9028 /* we want to have an optimal behaviour on single process mode to
9029 * maximize the work at once, but in multi-process we want to keep
9030 * some fairness between processes, so we target half of the max
9031 * number of events to be balanced over all the processes the proxy
9032 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9033 * used to disable the limit.
9034 */
9035 if (listener->maxaccept > 0) {
9036 if (nbproc > 1)
9037 listener->maxaccept = (listener->maxaccept + 1) / 2;
9038 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9039 }
9040
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009041 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009042 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009043 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009044 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009045
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009046 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009047 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009048
Willy Tarreau620408f2016-10-21 16:37:51 +02009049 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9050 listener->options |= LI_O_TCP_L5_RULES;
9051
Willy Tarreaude3041d2010-05-31 10:56:17 +02009052 if (curproxy->mon_mask.s_addr)
9053 listener->options |= LI_O_CHK_MONNET;
9054
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009055 /* smart accept mode is automatic in HTTP mode */
9056 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009057 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009058 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9059 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009060 }
9061
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009062 /* Release unused SSL configs */
9063 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009064 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9065 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009066 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009067
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009068 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009069 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009070 int count, maxproc = 0;
9071
9072 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009073 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009074 if (count > maxproc)
9075 maxproc = count;
9076 }
9077 /* backends have 0, frontends have 1 or more */
9078 if (maxproc != 1)
9079 Warning("Proxy '%s': in multi-process mode, stats will be"
9080 " limited to process assigned to the current request.\n",
9081 curproxy->id);
9082
Willy Tarreau102df612014-05-07 23:56:38 +02009083 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9084 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9085 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009086 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009087 }
Willy Tarreau102df612014-05-07 23:56:38 +02009088 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9089 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9090 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009091 }
9092 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009093
9094 /* create the task associated with the proxy */
9095 curproxy->task = task_new();
9096 if (curproxy->task) {
9097 curproxy->task->context = curproxy;
9098 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009099 } else {
9100 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9101 curproxy->id);
9102 cfgerr++;
9103 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009104 }
9105
Willy Tarreaufbb78422011-06-05 15:38:35 +02009106 /* automatically compute fullconn if not set. We must not do it in the
9107 * loop above because cross-references are not yet fully resolved.
9108 */
9109 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9110 /* If <fullconn> is not set, let's set it to 10% of the sum of
9111 * the possible incoming frontend's maxconns.
9112 */
9113 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009114 /* we have the sum of the maxconns in <total>. We only
9115 * keep 10% of that sum to set the default fullconn, with
9116 * a hard minimum of 1 (to avoid a divide by zero).
9117 */
Emeric Brun3f783572017-01-12 11:21:28 +01009118 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009119 if (!curproxy->fullconn)
9120 curproxy->fullconn = 1;
9121 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009122 }
9123
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009124 /*
9125 * Recount currently required checks.
9126 */
9127
9128 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9129 int optnum;
9130
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009131 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9132 if (curproxy->options & cfg_opts[optnum].val)
9133 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009134
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009135 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9136 if (curproxy->options2 & cfg_opts2[optnum].val)
9137 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009138 }
9139
Willy Tarreau0fca4832015-05-01 19:12:05 +02009140 /* compute the required process bindings for the peers */
9141 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9142 if (curproxy->table.peers.p)
9143 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9144
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009145 if (cfg_peers) {
9146 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009147 struct peer *p, *pb;
9148
Willy Tarreau1e273012015-05-01 19:15:17 +02009149 /* Remove all peers sections which don't have a valid listener,
9150 * which are not used by any table, or which are bound to more
9151 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009152 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009153 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009154 while (*last) {
9155 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009156
9157 if (curpeers->state == PR_STSTOPPED) {
9158 /* the "disabled" keyword was present */
9159 if (curpeers->peers_fe)
9160 stop_proxy(curpeers->peers_fe);
9161 curpeers->peers_fe = NULL;
9162 }
9163 else if (!curpeers->peers_fe) {
9164 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9165 curpeers->id, localpeer);
9166 }
David Carliere6c39412015-07-02 07:00:17 +00009167 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009168 /* either it's totally stopped or too much used */
9169 if (curpeers->peers_fe->bind_proc) {
9170 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009171 "running in different processes (%d different ones). "
9172 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009173 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009174 cfgerr++;
9175 }
9176 stop_proxy(curpeers->peers_fe);
9177 curpeers->peers_fe = NULL;
9178 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009179 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009180 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009181 last = &curpeers->next;
9182 continue;
9183 }
9184
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009185 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009186 p = curpeers->remote;
9187 while (p) {
9188 pb = p->next;
9189 free(p->id);
9190 free(p);
9191 p = pb;
9192 }
9193
9194 /* Destroy and unlink this curpeers section.
9195 * Note: curpeers is backed up into *last.
9196 */
9197 free(curpeers->id);
9198 curpeers = curpeers->next;
9199 free(*last);
9200 *last = curpeers;
9201 }
9202 }
9203
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009204 /* initialize stick-tables on backend capable proxies. This must not
9205 * be done earlier because the data size may be discovered while parsing
9206 * other proxies.
9207 */
9208 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9209 if (curproxy->state == PR_STSTOPPED)
9210 continue;
9211
9212 if (!stktable_init(&curproxy->table)) {
9213 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9214 cfgerr++;
9215 }
9216 }
9217
Simon Horman0d16a402015-01-30 11:22:58 +09009218 if (mailers) {
9219 struct mailers *curmailers = mailers, **last;
9220 struct mailer *m, *mb;
9221
9222 /* Remove all mailers sections which don't have a valid listener.
9223 * This can happen when a mailers section is never referenced.
9224 */
9225 last = &mailers;
9226 while (*last) {
9227 curmailers = *last;
9228 if (curmailers->users) {
9229 last = &curmailers->next;
9230 continue;
9231 }
9232
9233 Warning("Removing incomplete section 'mailers %s'.\n",
9234 curmailers->id);
9235
9236 m = curmailers->mailer_list;
9237 while (m) {
9238 mb = m->next;
9239 free(m->id);
9240 free(m);
9241 m = mb;
9242 }
9243
9244 /* Destroy and unlink this curmailers section.
9245 * Note: curmailers is backed up into *last.
9246 */
9247 free(curmailers->id);
9248 curmailers = curmailers->next;
9249 free(*last);
9250 *last = curmailers;
9251 }
9252 }
9253
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009254 /* Update server_state_file_name to backend name if backend is supposed to use
9255 * a server-state file locally defined and none has been provided */
9256 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9257 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9258 curproxy->server_state_file_name == NULL)
9259 curproxy->server_state_file_name = strdup(curproxy->id);
9260 }
9261
Willy Tarreau34eb6712011-10-24 18:15:04 +02009262 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009263 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009264 MEM_F_SHARED);
9265
Willy Tarreaubb925012009-07-23 13:36:36 +02009266 if (cfgerr > 0)
9267 err_code |= ERR_ALERT | ERR_FATAL;
9268 out:
9269 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009270}
9271
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009272/*
9273 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9274 * parsing sessions.
9275 */
9276void cfg_register_keywords(struct cfg_kw_list *kwl)
9277{
9278 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9279}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009280
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009281/*
9282 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9283 */
9284void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9285{
9286 LIST_DEL(&kwl->list);
9287 LIST_INIT(&kwl->list);
9288}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009289
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009290/* this function register new section in the haproxy configuration file.
9291 * <section_name> is the name of this new section and <section_parser>
9292 * is the called parser. If two section declaration have the same name,
9293 * only the first declared is used.
9294 */
9295int cfg_register_section(char *section_name,
9296 int (*section_parser)(const char *, int, char **, int))
9297{
9298 struct cfg_section *cs;
9299
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009300 list_for_each_entry(cs, &sections, list) {
9301 if (strcmp(cs->section_name, section_name) == 0) {
9302 Alert("register section '%s': already registered.\n", section_name);
9303 return 0;
9304 }
9305 }
9306
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009307 cs = calloc(1, sizeof(*cs));
9308 if (!cs) {
9309 Alert("register section '%s': out of memory.\n", section_name);
9310 return 0;
9311 }
9312
9313 cs->section_name = section_name;
9314 cs->section_parser = section_parser;
9315
9316 LIST_ADDQ(&sections, &cs->list);
9317
9318 return 1;
9319}
9320
Willy Tarreaubaaee002006-06-26 02:48:02 +02009321/*
David Carlier845efb52015-09-25 11:49:18 +01009322 * free all config section entries
9323 */
9324void cfg_unregister_sections(void)
9325{
9326 struct cfg_section *cs, *ics;
9327
9328 list_for_each_entry_safe(cs, ics, &sections, list) {
9329 LIST_DEL(&cs->list);
9330 free(cs);
9331 }
9332}
9333
Christopher Faulet7110b402016-10-26 11:09:44 +02009334void cfg_backup_sections(struct list *backup_sections)
9335{
9336 struct cfg_section *cs, *ics;
9337
9338 list_for_each_entry_safe(cs, ics, &sections, list) {
9339 LIST_DEL(&cs->list);
9340 LIST_ADDQ(backup_sections, &cs->list);
9341 }
9342}
9343
9344void cfg_restore_sections(struct list *backup_sections)
9345{
9346 struct cfg_section *cs, *ics;
9347
9348 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9349 LIST_DEL(&cs->list);
9350 LIST_ADDQ(&sections, &cs->list);
9351 }
9352}
9353
Willy Tarreau659fbf02016-05-26 17:55:28 +02009354__attribute__((constructor))
9355static void cfgparse_init(void)
9356{
9357 /* Register internal sections */
9358 cfg_register_section("listen", cfg_parse_listen);
9359 cfg_register_section("frontend", cfg_parse_listen);
9360 cfg_register_section("backend", cfg_parse_listen);
9361 cfg_register_section("defaults", cfg_parse_listen);
9362 cfg_register_section("global", cfg_parse_global);
9363 cfg_register_section("userlist", cfg_parse_users);
9364 cfg_register_section("peers", cfg_parse_peers);
9365 cfg_register_section("mailers", cfg_parse_mailers);
9366 cfg_register_section("namespace_list", cfg_parse_netns);
9367 cfg_register_section("resolvers", cfg_parse_resolvers);
9368}
9369
David Carlier845efb52015-09-25 11:49:18 +01009370/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009371 * Local variables:
9372 * c-indent-level: 8
9373 * c-basic-offset: 8
9374 * End:
9375 */