blob: bdf63c2add319a4cc3c0b210376f99f4bd3d9123 [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;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002078 l->analysers |= curpeers->peers_fe->fe_req_ana;
2079 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002080 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2081 global.maxsock += l->maxconn;
2082 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002083 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002084 else {
2085 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2086 file, linenum, args[0], args[1],
2087 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2088 err_code |= ERR_FATAL;
2089 goto out;
2090 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002091 }
2092 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002093 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2094 curpeers->state = PR_STSTOPPED;
2095 }
2096 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2097 curpeers->state = PR_STNEW;
2098 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 else if (*args[0] != 0) {
2100 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
2103 }
2104
2105out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002106 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002107 return err_code;
2108}
2109
Baptiste Assmann325137d2015-04-13 23:40:55 +02002110/*
2111 * Parse a <resolvers> section.
2112 * Returns the error code, 0 if OK, or any combination of :
2113 * - ERR_ABORT: must abort ASAP
2114 * - ERR_FATAL: we can continue parsing but not start the service
2115 * - ERR_WARN: a warning has been emitted
2116 * - ERR_ALERT: an alert has been emitted
2117 * Only the two first ones can stop processing, the two others are just
2118 * indicators.
2119 */
2120int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2121{
2122 static struct dns_resolvers *curr_resolvers = NULL;
2123 struct dns_nameserver *newnameserver = NULL;
2124 const char *err;
2125 int err_code = 0;
2126 char *errmsg = NULL;
2127
2128 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2129 if (!*args[1]) {
2130 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2131 err_code |= ERR_ALERT | ERR_ABORT;
2132 goto out;
2133 }
2134
2135 err = invalid_char(args[1]);
2136 if (err) {
2137 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2138 file, linenum, *err, args[0], args[1]);
2139 err_code |= ERR_ALERT | ERR_ABORT;
2140 goto out;
2141 }
2142
2143 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2144 /* Error if two resolvers owns the same name */
2145 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2146 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2147 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2148 err_code |= ERR_ALERT | ERR_ABORT;
2149 }
2150 }
2151
Vincent Bernat02779b62016-04-03 13:48:43 +02002152 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2154 err_code |= ERR_ALERT | ERR_ABORT;
2155 goto out;
2156 }
2157
2158 /* default values */
2159 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2160 curr_resolvers->conf.file = strdup(file);
2161 curr_resolvers->conf.line = linenum;
2162 curr_resolvers->id = strdup(args[1]);
2163 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002164 /* default maximum response size */
2165 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002166 /* default hold period for nx, other, refuse and timeout is 30s */
2167 curr_resolvers->hold.nx = 30000;
2168 curr_resolvers->hold.other = 30000;
2169 curr_resolvers->hold.refused = 30000;
2170 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002171 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002172 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002173 curr_resolvers->hold.valid = 10000;
2174 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002175 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002176 /* default resolution pool size */
2177 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002178 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002179 LIST_INIT(&curr_resolvers->resolution.curr);
2180 LIST_INIT(&curr_resolvers->resolution.wait);
2181 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002182 }
2183 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2184 struct sockaddr_storage *sk;
2185 int port1, port2;
2186 struct protocol *proto;
2187
2188 if (!*args[2]) {
2189 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2190 file, linenum, args[0]);
2191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
2193 }
2194
2195 err = invalid_char(args[1]);
2196 if (err) {
2197 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2198 file, linenum, *err, args[1]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
Baptiste Assmanna315c552015-11-02 22:55:49 +01002203 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2204 /* Error if two resolvers owns the same name */
2205 if (strcmp(newnameserver->id, args[1]) == 0) {
2206 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2207 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2208 err_code |= ERR_ALERT | ERR_FATAL;
2209 }
2210 }
2211
Vincent Bernat02779b62016-04-03 13:48:43 +02002212 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002213 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2214 err_code |= ERR_ALERT | ERR_ABORT;
2215 goto out;
2216 }
2217
2218 /* the nameservers are linked backward first */
2219 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2220 curr_resolvers->count_nameservers++;
2221 newnameserver->resolvers = curr_resolvers;
2222 newnameserver->conf.file = strdup(file);
2223 newnameserver->conf.line = linenum;
2224 newnameserver->id = strdup(args[1]);
2225
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002226 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002227 if (!sk) {
2228 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232
2233 proto = protocol_by_family(sk->ss_family);
2234 if (!proto || !proto->connect) {
2235 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2236 file, linenum, args[0], args[1]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240
2241 if (port1 != port2) {
2242 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2243 file, linenum, args[0], args[1], args[2]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002248 if (!port1 && !port2) {
2249 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2250 file, linenum, args[0], args[1]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
Baptiste Assmann325137d2015-04-13 23:40:55 +02002255 newnameserver->addr = *sk;
2256 }
2257 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2258 const char *res;
2259 unsigned int time;
2260
2261 if (!*args[2]) {
2262 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2263 file, linenum, args[0]);
2264 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2269 if (res) {
2270 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2271 file, linenum, *res, args[0]);
2272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
2274 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002275 if (strcmp(args[1], "nx") == 0)
2276 curr_resolvers->hold.nx = time;
2277 else if (strcmp(args[1], "other") == 0)
2278 curr_resolvers->hold.other = time;
2279 else if (strcmp(args[1], "refused") == 0)
2280 curr_resolvers->hold.refused = time;
2281 else if (strcmp(args[1], "timeout") == 0)
2282 curr_resolvers->hold.timeout = time;
2283 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002284 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002285 else if (strcmp(args[1], "obsolete") == 0)
2286 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002287 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002288 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002289 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002295 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002296 int i = 0;
2297
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002298 if (!*args[1]) {
2299 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2300 file, linenum, args[0]);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
2303 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002304
2305 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002306 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2307 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2308 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002314 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002315 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2316 if (!*args[1]) {
2317 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2318 file, linenum, args[0]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 curr_resolvers->resolution_pool_size = atoi(args[1]);
2323 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002324 else if (strcmp(args[0], "resolve_retries") == 0) {
2325 if (!*args[1]) {
2326 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2327 file, linenum, args[0]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 curr_resolvers->resolve_retries = atoi(args[1]);
2332 }
2333 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002334 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002335 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002340 else if (strcmp(args[1], "retry") == 0) {
2341 const char *res;
2342 unsigned int timeout_retry;
2343
2344 if (!*args[2]) {
2345 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2346 file, linenum, args[0], args[1]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2351 if (res) {
2352 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2353 file, linenum, *res, args[0], args[1]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357 curr_resolvers->timeout.retry = timeout_retry;
2358 }
2359 else {
2360 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2361 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002365 } /* neither "nameserver" nor "resolvers" */
2366 else if (*args[0] != 0) {
2367 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
2371
2372 out:
2373 free(errmsg);
2374 return err_code;
2375}
Simon Horman0d16a402015-01-30 11:22:58 +09002376
2377/*
William Lallemand51097192015-04-14 16:35:22 +02002378 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002379 * Returns the error code, 0 if OK, or any combination of :
2380 * - ERR_ABORT: must abort ASAP
2381 * - ERR_FATAL: we can continue parsing but not start the service
2382 * - ERR_WARN: a warning has been emitted
2383 * - ERR_ALERT: an alert has been emitted
2384 * Only the two first ones can stop processing, the two others are just
2385 * indicators.
2386 */
2387int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2388{
2389 static struct mailers *curmailers = NULL;
2390 struct mailer *newmailer = NULL;
2391 const char *err;
2392 int err_code = 0;
2393 char *errmsg = NULL;
2394
2395 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2396 if (!*args[1]) {
2397 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2398 err_code |= ERR_ALERT | ERR_ABORT;
2399 goto out;
2400 }
2401
2402 err = invalid_char(args[1]);
2403 if (err) {
2404 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2405 file, linenum, *err, args[0], args[1]);
2406 err_code |= ERR_ALERT | ERR_ABORT;
2407 goto out;
2408 }
2409
2410 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2411 /*
2412 * If there are two proxies with the same name only following
2413 * combinations are allowed:
2414 */
2415 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002416 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 +09002417 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002419 }
2420 }
2421
Vincent Bernat02779b62016-04-03 13:48:43 +02002422 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002423 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2424 err_code |= ERR_ALERT | ERR_ABORT;
2425 goto out;
2426 }
2427
2428 curmailers->next = mailers;
2429 mailers = curmailers;
2430 curmailers->conf.file = strdup(file);
2431 curmailers->conf.line = linenum;
2432 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002433 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2434 * But need enough time so that timeouts don't occur
2435 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002436 }
2437 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2438 struct sockaddr_storage *sk;
2439 int port1, port2;
2440 struct protocol *proto;
2441
2442 if (!*args[2]) {
2443 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2444 file, linenum, args[0]);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448
2449 err = invalid_char(args[1]);
2450 if (err) {
2451 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2452 file, linenum, *err, args[1]);
2453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
2455 }
2456
Vincent Bernat02779b62016-04-03 13:48:43 +02002457 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002458 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2459 err_code |= ERR_ALERT | ERR_ABORT;
2460 goto out;
2461 }
2462
2463 /* the mailers are linked backwards first */
2464 curmailers->count++;
2465 newmailer->next = curmailers->mailer_list;
2466 curmailers->mailer_list = newmailer;
2467 newmailer->mailers = curmailers;
2468 newmailer->conf.file = strdup(file);
2469 newmailer->conf.line = linenum;
2470
2471 newmailer->id = strdup(args[1]);
2472
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002473 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002474 if (!sk) {
2475 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479
2480 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002481 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2482 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002483 file, linenum, args[0], args[1]);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
2488 if (port1 != port2) {
2489 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2490 file, linenum, args[0], args[1], args[2]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
2495 if (!port1) {
2496 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2497 file, linenum, args[0], args[1], args[2]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501
2502 newmailer->addr = *sk;
2503 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002504 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002505 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002506 }
2507 else if (strcmp(args[0], "timeout") == 0) {
2508 if (!*args[1]) {
2509 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2510 file, linenum, args[0]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 else if (strcmp(args[1], "mail") == 0) {
2515 const char *res;
2516 unsigned int timeout_mail;
2517 if (!*args[2]) {
2518 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2519 file, linenum, args[0], args[1]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2524 if (res) {
2525 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2526 file, linenum, *res, args[0]);
2527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
2529 }
2530 if (timeout_mail <= 0) {
2531 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535 curmailers->timeout.mail = timeout_mail;
2536 } else {
2537 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2538 file, linenum, args[0], args[1]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542 }
Simon Horman0d16a402015-01-30 11:22:58 +09002543 else if (*args[0] != 0) {
2544 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
2547 }
2548
2549out:
2550 free(errmsg);
2551 return err_code;
2552}
2553
Simon Horman9dc49962015-01-30 11:22:59 +09002554static void free_email_alert(struct proxy *p)
2555{
2556 free(p->email_alert.mailers.name);
2557 p->email_alert.mailers.name = NULL;
2558 free(p->email_alert.from);
2559 p->email_alert.from = NULL;
2560 free(p->email_alert.to);
2561 p->email_alert.to = NULL;
2562 free(p->email_alert.myhostname);
2563 p->email_alert.myhostname = NULL;
2564}
2565
Willy Tarreau3842f002009-06-14 11:39:52 +02002566int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567{
2568 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002569 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002570 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002571 int rc;
2572 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002573 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002574 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002575 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002576 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002577 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 if (!strcmp(args[0], "listen"))
2580 rc = PR_CAP_LISTEN;
2581 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002582 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002583 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002584 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002585 else
2586 rc = PR_CAP_NONE;
2587
2588 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 if (!*args[1]) {
2590 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002591 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_ABORT;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002596
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002597 err = invalid_char(args[1]);
2598 if (err) {
2599 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2600 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002602 }
2603
Willy Tarreau8f50b682015-05-26 11:45:02 +02002604 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2605 if (curproxy) {
2606 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2607 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2608 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002610 }
2611
Vincent Bernat02779b62016-04-03 13:48:43 +02002612 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_ABORT;
2615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002617
Willy Tarreau97cb7802010-01-03 20:23:58 +01002618 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 curproxy->next = proxy;
2620 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002621 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2622 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002623 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002625 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002626 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627
William Lallemand6e62fb62015-04-28 16:55:23 +02002628 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2629 if (curproxy->cap & PR_CAP_FE)
2630 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 }
2633
2634 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002635 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002636 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002637
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002640 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002641 curproxy->no_options = defproxy.no_options;
2642 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002643 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002644 curproxy->except_net = defproxy.except_net;
2645 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002646 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002647 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002649 if (defproxy.fwdfor_hdr_len) {
2650 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2651 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2652 }
2653
Willy Tarreaub86db342009-11-30 11:50:16 +01002654 if (defproxy.orgto_hdr_len) {
2655 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2656 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2657 }
2658
Mark Lamourinec2247f02012-01-04 13:02:01 -05002659 if (defproxy.server_id_hdr_len) {
2660 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2661 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2662 }
2663
Willy Tarreau977b8e42006-12-29 14:19:17 +01002664 if (curproxy->cap & PR_CAP_FE) {
2665 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002666 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002667 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668
2669 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002670 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2671 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672
2673 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002677 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002678 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 curproxy->fullconn = defproxy.fullconn;
2680 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002681 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002682 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002684 if (defproxy.check_req) {
2685 curproxy->check_req = calloc(1, defproxy.check_len);
2686 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2687 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002688 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002690 if (defproxy.expect_str) {
2691 curproxy->expect_str = strdup(defproxy.expect_str);
2692 if (defproxy.expect_regex) {
2693 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002694 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2695 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002696 }
2697 }
2698
Willy Tarreau67402132012-05-31 20:40:20 +02002699 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 if (defproxy.cookie_name)
2701 curproxy->cookie_name = strdup(defproxy.cookie_name);
2702 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002703
2704 if (defproxy.dyncookie_key)
2705 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002706 if (defproxy.cookie_domain)
2707 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002708
Willy Tarreau31936852010-10-06 16:59:56 +02002709 if (defproxy.cookie_maxidle)
2710 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2711
2712 if (defproxy.cookie_maxlife)
2713 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2714
Emeric Brun647caf12009-06-30 17:57:00 +02002715 if (defproxy.rdp_cookie_name)
2716 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2717 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2718
Willy Tarreau01732802007-11-01 22:48:15 +01002719 if (defproxy.url_param_name)
2720 curproxy->url_param_name = strdup(defproxy.url_param_name);
2721 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002722
Benoitaffb4812009-03-25 13:02:10 +01002723 if (defproxy.hh_name)
2724 curproxy->hh_name = strdup(defproxy.hh_name);
2725 curproxy->hh_len = defproxy.hh_len;
2726 curproxy->hh_match_domain = defproxy.hh_match_domain;
2727
Willy Tarreauef9a3602012-12-08 22:29:20 +01002728 if (defproxy.conn_src.iface_name)
2729 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2730 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002731 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002732#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002733 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002734#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002735 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002738 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002739 if (defproxy.capture_name)
2740 curproxy->capture_name = strdup(defproxy.capture_name);
2741 curproxy->capture_namelen = defproxy.capture_namelen;
2742 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002746 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002747 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002748 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002749 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002750 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 curproxy->mon_net = defproxy.mon_net;
2752 curproxy->mon_mask = defproxy.mon_mask;
2753 if (defproxy.monitor_uri)
2754 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2755 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002756 if (defproxy.defbe.name)
2757 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002758
2759 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002760 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2761 if (curproxy->conf.logformat_string &&
2762 curproxy->conf.logformat_string != default_http_log_format &&
2763 curproxy->conf.logformat_string != default_tcp_log_format &&
2764 curproxy->conf.logformat_string != clf_http_log_format)
2765 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2766
2767 if (defproxy.conf.lfs_file) {
2768 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2769 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2770 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002771
2772 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2773 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2774 if (curproxy->conf.logformat_sd_string &&
2775 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2776 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2777
2778 if (defproxy.conf.lfsd_file) {
2779 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2780 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2781 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782 }
2783
2784 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002785 curproxy->timeout.connect = defproxy.timeout.connect;
2786 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002787 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002788 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002789 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002790 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002791 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002792 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002793 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002794 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 }
2796
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002798 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002799
2800 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002801 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002802 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002803 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002804 LIST_INIT(&node->list);
2805 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2806 }
2807
Willy Tarreau62a61232013-04-12 18:13:46 +02002808 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2809 if (curproxy->conf.uniqueid_format_string)
2810 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2811
Dragan Dosen43885c72015-10-01 13:18:13 +02002812 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002813
Willy Tarreau62a61232013-04-12 18:13:46 +02002814 if (defproxy.conf.uif_file) {
2815 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2816 curproxy->conf.uif_line = defproxy.conf.uif_line;
2817 }
William Lallemanda73203e2012-03-12 12:48:57 +01002818
2819 /* copy default header unique id */
2820 if (defproxy.header_unique_id)
2821 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2822
William Lallemand82fe75c2012-10-23 10:25:10 +02002823 /* default compression options */
2824 if (defproxy.comp != NULL) {
2825 curproxy->comp = calloc(1, sizeof(struct comp));
2826 curproxy->comp->algos = defproxy.comp->algos;
2827 curproxy->comp->types = defproxy.comp->types;
2828 }
2829
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002831 curproxy->conf.used_listener_id = EB_ROOT;
2832 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002833
Simon Horman98637e52014-06-20 12:30:16 +09002834 if (defproxy.check_path)
2835 curproxy->check_path = strdup(defproxy.check_path);
2836 if (defproxy.check_command)
2837 curproxy->check_command = strdup(defproxy.check_command);
2838
Simon Horman9dc49962015-01-30 11:22:59 +09002839 if (defproxy.email_alert.mailers.name)
2840 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2841 if (defproxy.email_alert.from)
2842 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2843 if (defproxy.email_alert.to)
2844 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2845 if (defproxy.email_alert.myhostname)
2846 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002847 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002848 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002849
Willy Tarreau93893792009-07-23 13:19:11 +02002850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
2852 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2853 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002854 /* FIXME-20070101: we should do this too at the end of the
2855 * config parsing to free all default values.
2856 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002857 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2858 err_code |= ERR_ABORT;
2859 goto out;
2860 }
2861
Willy Tarreaua534fea2008-08-03 12:19:50 +02002862 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002863 free(defproxy.check_command);
2864 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002865 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002866 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002867 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002868 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002869 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002870 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002871 free(defproxy.capture_name);
2872 free(defproxy.monitor_uri);
2873 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002874 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002875 free(defproxy.fwdfor_hdr_name);
2876 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002877 free(defproxy.orgto_hdr_name);
2878 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002879 free(defproxy.server_id_hdr_name);
2880 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002881 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002882 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002883 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002884 free(defproxy.expect_regex);
2885 defproxy.expect_regex = NULL;
2886 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002887
Willy Tarreau62a61232013-04-12 18:13:46 +02002888 if (defproxy.conf.logformat_string != default_http_log_format &&
2889 defproxy.conf.logformat_string != default_tcp_log_format &&
2890 defproxy.conf.logformat_string != clf_http_log_format)
2891 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002892
Willy Tarreau62a61232013-04-12 18:13:46 +02002893 free(defproxy.conf.uniqueid_format_string);
2894 free(defproxy.conf.lfs_file);
2895 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002896 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002897 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002898
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002899 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2900 free(defproxy.conf.logformat_sd_string);
2901 free(defproxy.conf.lfsd_file);
2902
Willy Tarreaua534fea2008-08-03 12:19:50 +02002903 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002904 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002905
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 /* we cannot free uri_auth because it might already be used */
2907 init_default_instance();
2908 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002909 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2910 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002911 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 }
2914 else if (curproxy == NULL) {
2915 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002919
2920 /* update the current file and line being parsed */
2921 curproxy->conf.args.file = curproxy->conf.file;
2922 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923
2924 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002925 if (!strcmp(args[0], "server") ||
2926 !strcmp(args[0], "default-server") ||
2927 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002928 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2929 if (err_code & ERR_FATAL)
2930 goto out;
2931 }
2932 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002933 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002934 int cur_arg;
2935
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 if (curproxy == &defproxy) {
2937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002941 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002942 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943
Willy Tarreau24709282013-03-10 21:32:12 +01002944 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002945 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002950
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002951 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002952
2953 /* use default settings for unix sockets */
2954 bind_conf->ux.uid = global.unix_bind.ux.uid;
2955 bind_conf->ux.gid = global.unix_bind.ux.gid;
2956 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002957
2958 /* NOTE: the following line might create several listeners if there
2959 * are comma-separated IPs or port ranges. So all further processing
2960 * will have to be applied to all listeners created after last_listen.
2961 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002962 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2963 if (errmsg && *errmsg) {
2964 indent_msg(&errmsg, 2);
2965 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002966 }
2967 else
2968 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2969 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002973
Willy Tarreau4348fad2012-09-20 16:48:07 +02002974 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2975 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002976 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002977 }
2978
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002979 cur_arg = 2;
2980 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002981 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002982 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002983 char *err;
2984
Willy Tarreau26982662012-09-12 23:17:10 +02002985 kw = bind_find_kw(args[cur_arg]);
2986 if (kw) {
2987 char *err = NULL;
2988 int code;
2989
2990 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002991 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2992 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002993 cur_arg += 1 + kw->skip ;
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
Willy Tarreau4348fad2012-09-20 16:48:07 +02002998 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002999 err_code |= code;
3000
3001 if (code) {
3002 if (err && *err) {
3003 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003004 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003005 }
3006 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003007 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3008 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003009 if (code & ERR_FATAL) {
3010 free(err);
3011 cur_arg += 1 + kw->skip;
3012 goto out;
3013 }
3014 }
3015 free(err);
3016 cur_arg += 1 + kw->skip;
3017 continue;
3018 }
3019
Willy Tarreau8638f482012-09-18 18:01:17 +02003020 err = NULL;
3021 if (!bind_dumped) {
3022 bind_dump_kws(&err);
3023 indent_msg(&err, 4);
3024 bind_dumped = 1;
3025 }
3026
3027 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3028 file, linenum, args[0], args[1], args[cur_arg],
3029 err ? " Registered keywords :" : "", err ? err : "");
3030 free(err);
3031
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003034 }
Willy Tarreau93893792009-07-23 13:19:11 +02003035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 }
3037 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003038 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003044 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003046
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 /* flush useless bits */
3048 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003051 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003052 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003054
William Lallemanddf1425a2015-04-28 20:17:49 +02003055 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3056 goto out;
3057
Willy Tarreau1c47f852006-07-09 08:22:27 +02003058 if (!*args[1]) {
3059 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003063 }
3064
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003066 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003067 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003068 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003069 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3070
Willy Tarreau93893792009-07-23 13:19:11 +02003071 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003074 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3075 goto out;
3076
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3078 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3079 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3080 else {
3081 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 }
3085 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003086 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003087 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003088
3089 if (curproxy == &defproxy) {
3090 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003094 }
3095
William Lallemanddf1425a2015-04-28 20:17:49 +02003096 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3097 goto out;
3098
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003099 if (!*args[1]) {
3100 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003104 }
3105
3106 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003107 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003108 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003109
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003110 if (curproxy->uuid <= 0) {
3111 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003112 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003115 }
3116
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003117 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3118 if (node) {
3119 struct proxy *target = container_of(node, struct proxy, conf.id);
3120 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3121 file, linenum, proxy_type_str(curproxy), curproxy->id,
3122 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003127 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003128 else if (!strcmp(args[0], "description")) {
3129 int i, len=0;
3130 char *d;
3131
Cyril Bonté99ed3272010-01-24 23:29:44 +01003132 if (curproxy == &defproxy) {
3133 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3134 file, linenum, args[0]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003139 if (!*args[1]) {
3140 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3141 file, linenum, args[0]);
3142 return -1;
3143 }
3144
Willy Tarreau348acfe2014-04-14 15:00:39 +02003145 for (i = 1; *args[i]; i++)
3146 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003147
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003148 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003149 curproxy->desc = d;
3150
Willy Tarreau348acfe2014-04-14 15:00:39 +02003151 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3152 for (i = 2; *args[i]; i++)
3153 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003154
3155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003157 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 curproxy->state = PR_STSTOPPED;
3160 }
3161 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003162 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 curproxy->state = PR_STNEW;
3165 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003166 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3167 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003168 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003169
3170 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003171 unsigned int low, high;
3172
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003173 if (strcmp(args[cur_arg], "all") == 0) {
3174 set = 0;
3175 break;
3176 }
3177 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003178 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003179 }
3180 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003181 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003182 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003183 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003184 char *dash = strchr(args[cur_arg], '-');
3185
3186 low = high = str2uic(args[cur_arg]);
3187 if (dash)
3188 high = str2uic(dash + 1);
3189
3190 if (high < low) {
3191 unsigned int swap = low;
3192 low = high;
3193 high = swap;
3194 }
3195
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003196 if (low < 1 || high > LONGBITS) {
3197 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3198 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003201 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003202 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003203 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003204 }
3205 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003206 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3207 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003210 }
3211 cur_arg++;
3212 }
3213 curproxy->bind_proc = set;
3214 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003215 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003216 if (curproxy == &defproxy) {
3217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003220 }
3221
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003222 err = invalid_char(args[1]);
3223 if (err) {
3224 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3225 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003227 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003228 }
3229
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003230 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003231 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3232 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003235 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003236 }
3237 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3238
3239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3240 err_code |= ERR_WARN;
3241
3242 if (*(args[1]) == 0) {
3243 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3244 file, linenum, args[0]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 free(curproxy->dyncookie_key);
3249 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3252 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253
Willy Tarreau977b8e42006-12-29 14:19:17 +01003254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003256
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 if (*(args[1]) == 0) {
3258 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3259 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003263
Willy Tarreau67402132012-05-31 20:40:20 +02003264 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003265 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003266 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003267 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 curproxy->cookie_name = strdup(args[1]);
3269 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003270
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 cur_arg = 2;
3272 while (*(args[cur_arg])) {
3273 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003274 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003277 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003280 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
3282 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003283 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
3285 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003286 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003288 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003289 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003292 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003294 else if (!strcmp(args[cur_arg], "httponly")) {
3295 curproxy->ck_opts |= PR_CK_HTTPONLY;
3296 }
3297 else if (!strcmp(args[cur_arg], "secure")) {
3298 curproxy->ck_opts |= PR_CK_SECURE;
3299 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003300 else if (!strcmp(args[cur_arg], "domain")) {
3301 if (!*args[cur_arg + 1]) {
3302 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3303 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003306 }
3307
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003308 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003309 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003310 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3311 " dots nor does not start with a dot."
3312 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003313 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003314 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003315 }
3316
3317 err = invalid_domainchar(args[cur_arg + 1]);
3318 if (err) {
3319 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3320 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003323 }
3324
Willy Tarreau68a897b2009-12-03 23:28:34 +01003325 if (!curproxy->cookie_domain) {
3326 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3327 } else {
3328 /* one domain was already specified, add another one by
3329 * building the string which will be returned along with
3330 * the cookie.
3331 */
3332 char *new_ptr;
3333 int new_len = strlen(curproxy->cookie_domain) +
3334 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3335 new_ptr = malloc(new_len);
3336 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3337 free(curproxy->cookie_domain);
3338 curproxy->cookie_domain = new_ptr;
3339 }
Willy Tarreau31936852010-10-06 16:59:56 +02003340 cur_arg++;
3341 }
3342 else if (!strcmp(args[cur_arg], "maxidle")) {
3343 unsigned int maxidle;
3344 const char *res;
3345
3346 if (!*args[cur_arg + 1]) {
3347 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3348 file, linenum, args[cur_arg]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352
3353 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3354 if (res) {
3355 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3356 file, linenum, *res, args[cur_arg]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360 curproxy->cookie_maxidle = maxidle;
3361 cur_arg++;
3362 }
3363 else if (!strcmp(args[cur_arg], "maxlife")) {
3364 unsigned int maxlife;
3365 const char *res;
3366
3367 if (!*args[cur_arg + 1]) {
3368 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3369 file, linenum, args[cur_arg]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
3373
3374 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3375 if (res) {
3376 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3377 file, linenum, *res, args[cur_arg]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003382 cur_arg++;
3383 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003384 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003385
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3387 err_code |= ERR_WARN;
3388 curproxy->ck_opts |= PR_CK_DYNAMIC;
3389 }
3390
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003392 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 +02003393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397 cur_arg++;
3398 }
Willy Tarreau67402132012-05-31 20:40:20 +02003399 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3401 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404
Willy Tarreau67402132012-05-31 20:40:20 +02003405 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3407 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003408 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003410
Willy Tarreau67402132012-05-31 20:40:20 +02003411 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003412 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3413 file, linenum);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003417 else if (!strcmp(args[0], "email-alert")) {
3418 if (*(args[1]) == 0) {
3419 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3420 file, linenum, args[0]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
3424
3425 if (!strcmp(args[1], "from")) {
3426 if (*(args[1]) == 0) {
3427 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3428 file, linenum, args[1]);
3429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
3431 }
3432 free(curproxy->email_alert.from);
3433 curproxy->email_alert.from = strdup(args[2]);
3434 }
3435 else if (!strcmp(args[1], "mailers")) {
3436 if (*(args[1]) == 0) {
3437 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3438 file, linenum, args[1]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 free(curproxy->email_alert.mailers.name);
3443 curproxy->email_alert.mailers.name = strdup(args[2]);
3444 }
3445 else if (!strcmp(args[1], "myhostname")) {
3446 if (*(args[1]) == 0) {
3447 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3448 file, linenum, args[1]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 free(curproxy->email_alert.myhostname);
3453 curproxy->email_alert.myhostname = strdup(args[2]);
3454 }
Simon Horman64e34162015-02-06 11:11:57 +09003455 else if (!strcmp(args[1], "level")) {
3456 curproxy->email_alert.level = get_log_level(args[2]);
3457 if (curproxy->email_alert.level < 0) {
3458 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3459 file, linenum, args[1], args[2]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463 }
Simon Horman9dc49962015-01-30 11:22:59 +09003464 else if (!strcmp(args[1], "to")) {
3465 if (*(args[1]) == 0) {
3466 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3467 file, linenum, args[1]);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
3471 free(curproxy->email_alert.to);
3472 curproxy->email_alert.to = strdup(args[2]);
3473 }
3474 else {
3475 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3476 file, linenum, args[1]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
Simon Horman64e34162015-02-06 11:11:57 +09003480 /* Indicate that the email_alert is at least partially configured */
3481 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003482 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003483 else if (!strcmp(args[0], "external-check")) {
3484 if (*(args[1]) == 0) {
3485 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3486 file, linenum, args[0]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490
3491 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003492 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003493 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003494 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003495 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3496 file, linenum, args[1]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500 free(curproxy->check_command);
3501 curproxy->check_command = strdup(args[2]);
3502 }
3503 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003504 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003505 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003506 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003507 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3508 file, linenum, args[1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512 free(curproxy->check_path);
3513 curproxy->check_path = strdup(args[2]);
3514 }
3515 else {
3516 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3517 file, linenum, args[1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003522 else if (!strcmp(args[0], "persist")) { /* persist */
3523 if (*(args[1]) == 0) {
3524 Alert("parsing [%s:%d] : missing persist method.\n",
3525 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003528 }
3529
3530 if (!strncmp(args[1], "rdp-cookie", 10)) {
3531 curproxy->options2 |= PR_O2_RDPC_PRST;
3532
Emeric Brunb982a3d2010-01-04 15:45:53 +01003533 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003534 const char *beg, *end;
3535
3536 beg = args[1] + 11;
3537 end = strchr(beg, ')');
3538
William Lallemanddf1425a2015-04-28 20:17:49 +02003539 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3540 goto out;
3541
Emeric Brun647caf12009-06-30 17:57:00 +02003542 if (!end || end == beg) {
3543 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3544 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003547 }
3548
3549 free(curproxy->rdp_cookie_name);
3550 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3551 curproxy->rdp_cookie_len = end-beg;
3552 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003553 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003554 free(curproxy->rdp_cookie_name);
3555 curproxy->rdp_cookie_name = strdup("msts");
3556 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3557 }
3558 else { /* syntax */
3559 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3560 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003563 }
3564 }
3565 else {
3566 Alert("parsing [%s:%d] : unknown persist method.\n",
3567 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003570 }
3571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003573 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003577 else if (!strcmp(args[0], "load-server-state-from-file")) {
3578 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3579 err_code |= ERR_WARN;
3580 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3581 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3582 }
3583 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3584 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3585 }
3586 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3587 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3588 }
3589 else {
3590 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3591 file, linenum, args[0], args[1]);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594 }
3595 }
3596 else if (!strcmp(args[0], "server-state-file-name")) {
3597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3598 err_code |= ERR_WARN;
3599 if (*(args[1]) == 0) {
3600 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3601 file, linenum, args[0]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605 else if (!strcmp(args[1], "use-backend-name"))
3606 curproxy->server_state_file_name = strdup(curproxy->id);
3607 else
3608 curproxy->server_state_file_name = strdup(args[1]);
3609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003611 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003615 if (curproxy == &defproxy) {
3616 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
3619 }
3620
William Lallemand1a748ae2015-05-19 16:37:23 +02003621 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3622 goto out;
3623
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 if (*(args[4]) == 0) {
3625 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003630 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 curproxy->capture_name = strdup(args[2]);
3632 curproxy->capture_namelen = strlen(curproxy->capture_name);
3633 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 curproxy->to_log |= LW_COOKIE;
3635 }
3636 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3637 struct cap_hdr *hdr;
3638
3639 if (curproxy == &defproxy) {
3640 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 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
3644
William Lallemand1a748ae2015-05-19 16:37:23 +02003645 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3646 goto out;
3647
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3649 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3650 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 }
3654
Vincent Bernat02779b62016-04-03 13:48:43 +02003655 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 hdr->next = curproxy->req_cap;
3657 hdr->name = strdup(args[3]);
3658 hdr->namelen = strlen(args[3]);
3659 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003660 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 hdr->index = curproxy->nb_req_cap++;
3662 curproxy->req_cap = hdr;
3663 curproxy->to_log |= LW_REQHDR;
3664 }
3665 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3666 struct cap_hdr *hdr;
3667
3668 if (curproxy == &defproxy) {
3669 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 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
3673
William Lallemand1a748ae2015-05-19 16:37:23 +02003674 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3675 goto out;
3676
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3678 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3679 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003683 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 hdr->next = curproxy->rsp_cap;
3685 hdr->name = strdup(args[3]);
3686 hdr->namelen = strlen(args[3]);
3687 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003688 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 hdr->index = curproxy->nb_rsp_cap++;
3690 curproxy->rsp_cap = hdr;
3691 curproxy->to_log |= LW_RSPHDR;
3692 }
3693 else {
3694 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3695 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 }
3699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003701 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003703
William Lallemanddf1425a2015-04-28 20:17:49 +02003704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3705 goto out;
3706
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 if (*(args[1]) == 0) {
3708 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
3713 curproxy->conn_retries = atol(args[1]);
3714 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003715 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003716 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003717
3718 if (curproxy == &defproxy) {
3719 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723
Willy Tarreau20b0de52012-12-24 15:45:22 +01003724 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003725 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003726 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3727 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3728 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3729 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003730 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 +01003731 file, linenum, args[0]);
3732 err_code |= ERR_WARN;
3733 }
3734
Willy Tarreauff011f22011-01-06 17:51:27 +01003735 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003736
Willy Tarreauff011f22011-01-06 17:51:27 +01003737 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003738 err_code |= ERR_ALERT | ERR_ABORT;
3739 goto out;
3740 }
3741
Willy Tarreau5002f572014-04-23 01:32:02 +02003742 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003743 err_code |= warnif_cond_conflicts(rule->cond,
3744 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3745 file, linenum);
3746
Willy Tarreauff011f22011-01-06 17:51:27 +01003747 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003748 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003749 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003750 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003751
3752 if (curproxy == &defproxy) {
3753 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
3756 }
3757
3758 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003759 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003760 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3761 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003762 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3763 file, linenum, args[0]);
3764 err_code |= ERR_WARN;
3765 }
3766
3767 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3768
3769 if (!rule) {
3770 err_code |= ERR_ALERT | ERR_ABORT;
3771 goto out;
3772 }
3773
3774 err_code |= warnif_cond_conflicts(rule->cond,
3775 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3776 file, linenum);
3777
3778 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3779 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003780 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3781 /* set the header name and length into the proxy structure */
3782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3783 err_code |= ERR_WARN;
3784
3785 if (!*args[1]) {
3786 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3787 file, linenum, args[0]);
3788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
3790 }
3791
3792 /* set the desired header name */
3793 free(curproxy->server_id_hdr_name);
3794 curproxy->server_id_hdr_name = strdup(args[1]);
3795 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3796 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003797 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003798 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003799
Willy Tarreaub099aca2008-10-12 17:26:37 +02003800 if (curproxy == &defproxy) {
3801 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003804 }
3805
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003806 /* emulate "block" using "http-request block". Since these rules are supposed to
3807 * be processed before all http-request rules, we put them into their own list
3808 * and will insert them at the end.
3809 */
3810 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3811 if (!rule) {
3812 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003813 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003814 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003815 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3816 err_code |= warnif_cond_conflicts(rule->cond,
3817 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3818 file, linenum);
3819 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003820
3821 if (!already_warned(WARN_BLOCK_DEPRECATED))
3822 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]);
3823
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003824 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003825 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003826 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003827
Cyril Bonté99ed3272010-01-24 23:29:44 +01003828 if (curproxy == &defproxy) {
3829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833
Willy Tarreaube4653b2015-05-28 15:26:58 +02003834 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003835 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3836 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003839 }
3840
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003841 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003842 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003843 err_code |= warnif_cond_conflicts(rule->cond,
3844 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3845 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003846 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003847 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003848 struct switching_rule *rule;
3849
Willy Tarreaub099aca2008-10-12 17:26:37 +02003850 if (curproxy == &defproxy) {
3851 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 }
3855
Willy Tarreau55ea7572007-06-17 19:56:27 +02003856 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003858
3859 if (*(args[1]) == 0) {
3860 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003863 }
3864
Willy Tarreauf51658d2014-04-23 01:21:56 +02003865 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3866 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3867 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3868 file, linenum, errmsg);
3869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
3871 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003872
Willy Tarreauf51658d2014-04-23 01:21:56 +02003873 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003874 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003875 else if (*args[2]) {
3876 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3877 file, linenum, args[2]);
3878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
3880 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003881
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003882 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003883 if (!rule) {
3884 Alert("Out of memory error.\n");
3885 goto out;
3886 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003887 rule->cond = cond;
3888 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003889 rule->line = linenum;
3890 rule->file = strdup(file);
3891 if (!rule->file) {
3892 Alert("Out of memory error.\n");
3893 goto out;
3894 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003895 LIST_INIT(&rule->list);
3896 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3897 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003898 else if (strcmp(args[0], "use-server") == 0) {
3899 struct server_rule *rule;
3900
3901 if (curproxy == &defproxy) {
3902 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906
3907 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3908 err_code |= ERR_WARN;
3909
3910 if (*(args[1]) == 0) {
3911 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915
3916 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3917 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3918 file, linenum, args[0]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003923 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3924 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3925 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003930 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003931
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003932 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003933 rule->cond = cond;
3934 rule->srv.name = strdup(args[1]);
3935 LIST_INIT(&rule->list);
3936 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3937 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3938 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003939 else if ((!strcmp(args[0], "force-persist")) ||
3940 (!strcmp(args[0], "ignore-persist"))) {
3941 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003942
3943 if (curproxy == &defproxy) {
3944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948
3949 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3950 err_code |= ERR_WARN;
3951
Willy Tarreauef6494c2010-01-28 17:12:36 +01003952 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003953 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3954 file, linenum, args[0]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003959 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3960 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3961 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
3964 }
3965
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003966 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3967 * where force-persist is applied.
3968 */
3969 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003970
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003971 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003972 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003973 if (!strcmp(args[0], "force-persist")) {
3974 rule->type = PERSIST_TYPE_FORCE;
3975 } else {
3976 rule->type = PERSIST_TYPE_IGNORE;
3977 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003978 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003979 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003980 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003981 else if (!strcmp(args[0], "stick-table")) {
3982 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003983 struct proxy *other;
3984
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003985 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003986 if (other) {
3987 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3988 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003992
Emeric Brun32da3c42010-09-23 18:39:19 +02003993 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003994 curproxy->table.type = (unsigned int)-1;
3995 while (*args[myidx]) {
3996 const char *err;
3997
3998 if (strcmp(args[myidx], "size") == 0) {
3999 myidx++;
4000 if (!*(args[myidx])) {
4001 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4002 file, linenum, args[myidx-1]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005 }
4006 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4007 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4008 file, linenum, *err, args[myidx-1]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004012 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004013 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004014 else if (strcmp(args[myidx], "peers") == 0) {
4015 myidx++;
Godbach50523162013-12-11 19:48:57 +08004016 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004017 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4018 file, linenum, args[myidx-1]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Godbach50523162013-12-11 19:48:57 +08004021 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004022 curproxy->table.peers.name = strdup(args[myidx++]);
4023 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004024 else if (strcmp(args[myidx], "expire") == 0) {
4025 myidx++;
4026 if (!*(args[myidx])) {
4027 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4028 file, linenum, args[myidx-1]);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
4032 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4033 if (err) {
4034 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4035 file, linenum, *err, args[myidx-1]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004039 if (val > INT_MAX) {
4040 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4041 file, linenum, val);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004045 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004046 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 }
4048 else if (strcmp(args[myidx], "nopurge") == 0) {
4049 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004050 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004051 }
4052 else if (strcmp(args[myidx], "type") == 0) {
4053 myidx++;
4054 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4055 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4056 file, linenum, args[myidx]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004060 /* myidx already points to next arg */
4061 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004062 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004063 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004064 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004065
4066 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004067 nw = args[myidx];
4068 while (*nw) {
4069 /* the "store" keyword supports a comma-separated list */
4070 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004071 sa = NULL; /* store arg */
4072 while (*nw && *nw != ',') {
4073 if (*nw == '(') {
4074 *nw = 0;
4075 sa = ++nw;
4076 while (*nw != ')') {
4077 if (!*nw) {
4078 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4079 file, linenum, args[0], cw);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
4083 nw++;
4084 }
4085 *nw = '\0';
4086 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004087 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004088 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004089 if (*nw)
4090 *nw++ = '\0';
4091 type = stktable_get_data_type(cw);
4092 if (type < 0) {
4093 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4094 file, linenum, args[0], cw);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
Willy Tarreauac782882010-06-20 10:41:54 +02004098
4099 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4100 switch (err) {
4101 case PE_NONE: break;
4102 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004103 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4104 file, linenum, args[0], cw);
4105 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004106 break;
4107
4108 case PE_ARG_MISSING:
4109 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4110 file, linenum, args[0], cw);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113
4114 case PE_ARG_NOT_USED:
4115 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4116 file, linenum, args[0], cw);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119
4120 default:
4121 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4122 file, linenum, args[0], cw);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004125 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004126 }
4127 myidx++;
4128 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004129 else {
4130 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4131 file, linenum, args[myidx]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004134 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 }
4136
4137 if (!curproxy->table.size) {
4138 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4139 file, linenum);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143
4144 if (curproxy->table.type == (unsigned int)-1) {
4145 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4146 file, linenum);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150 }
4151 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004153 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 int myidx = 0;
4155 const char *name = NULL;
4156 int flags;
4157
4158 if (curproxy == &defproxy) {
4159 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
4163
4164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4165 err_code |= ERR_WARN;
4166 goto out;
4167 }
4168
4169 myidx++;
4170 if ((strcmp(args[myidx], "store") == 0) ||
4171 (strcmp(args[myidx], "store-request") == 0)) {
4172 myidx++;
4173 flags = STK_IS_STORE;
4174 }
4175 else if (strcmp(args[myidx], "store-response") == 0) {
4176 myidx++;
4177 flags = STK_IS_STORE | STK_ON_RSP;
4178 }
4179 else if (strcmp(args[myidx], "match") == 0) {
4180 myidx++;
4181 flags = STK_IS_MATCH;
4182 }
4183 else if (strcmp(args[myidx], "on") == 0) {
4184 myidx++;
4185 flags = STK_IS_MATCH | STK_IS_STORE;
4186 }
4187 else {
4188 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
4191 }
4192
4193 if (*(args[myidx]) == 0) {
4194 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004199 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004200 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004201 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004202 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
4206
4207 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004208 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4209 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4210 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004211 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004212 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004213 goto out;
4214 }
4215 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004216 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4217 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4218 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004219 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004220 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004221 goto out;
4222 }
4223 }
4224
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004225 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004226 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004227
Emeric Brunb982a3d2010-01-04 15:45:53 +01004228 if (strcmp(args[myidx], "table") == 0) {
4229 myidx++;
4230 name = args[myidx++];
4231 }
4232
Willy Tarreauef6494c2010-01-28 17:12:36 +01004233 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004234 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4235 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4236 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004237 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004238 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 goto out;
4240 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004241 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004242 else if (*(args[myidx])) {
4243 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4244 file, linenum, args[0], args[myidx]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004246 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004247 goto out;
4248 }
Emeric Brun97679e72010-09-23 17:56:44 +02004249 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004250 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004251 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004252 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004253
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004254 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004255 rule->cond = cond;
4256 rule->expr = expr;
4257 rule->flags = flags;
4258 rule->table.name = name ? strdup(name) : NULL;
4259 LIST_INIT(&rule->list);
4260 if (flags & STK_ON_RSP)
4261 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4262 else
4263 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265 else if (!strcmp(args[0], "stats")) {
4266 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4267 curproxy->uri_auth = NULL; /* we must detach from the default config */
4268
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004269 if (!*args[1]) {
4270 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004271 } else if (!strcmp(args[1], "admin")) {
4272 struct stats_admin_rule *rule;
4273
4274 if (curproxy == &defproxy) {
4275 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4281 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4282 err_code |= ERR_ALERT | ERR_ABORT;
4283 goto out;
4284 }
4285
4286 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4287 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4288 file, linenum, args[0], args[1]);
4289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
4291 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004292 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4293 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4294 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004299 err_code |= warnif_cond_conflicts(cond,
4300 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4301 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004302
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004303 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004304 rule->cond = cond;
4305 LIST_INIT(&rule->list);
4306 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 } else if (!strcmp(args[1], "uri")) {
4308 if (*(args[2]) == 0) {
4309 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 }
4317 } else if (!strcmp(args[1], "realm")) {
4318 if (*(args[2]) == 0) {
4319 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4323 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_ABORT;
4325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004327 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004328 unsigned interval;
4329
4330 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4331 if (err) {
4332 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4333 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004336 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_ABORT;
4339 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004340 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004341 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004342 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004343
4344 if (curproxy == &defproxy) {
4345 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349
4350 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4351 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4352 err_code |= ERR_ALERT | ERR_ABORT;
4353 goto out;
4354 }
4355
Willy Tarreauff011f22011-01-06 17:51:27 +01004356 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004357 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004358 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4359 file, linenum, args[0]);
4360 err_code |= ERR_WARN;
4361 }
4362
Willy Tarreauff011f22011-01-06 17:51:27 +01004363 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004364
Willy Tarreauff011f22011-01-06 17:51:27 +01004365 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004366 err_code |= ERR_ALERT | ERR_ABORT;
4367 goto out;
4368 }
4369
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004370 err_code |= warnif_cond_conflicts(rule->cond,
4371 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4372 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004373 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004374
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 } else if (!strcmp(args[1], "auth")) {
4376 if (*(args[2]) == 0) {
4377 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_ABORT;
4383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 }
4385 } else if (!strcmp(args[1], "scope")) {
4386 if (*(args[2]) == 0) {
4387 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4391 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_ALERT | ERR_ABORT;
4393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 }
4395 } else if (!strcmp(args[1], "enable")) {
4396 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4397 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_ABORT;
4399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004401 } else if (!strcmp(args[1], "hide-version")) {
4402 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4403 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_ABORT;
4405 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004406 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004407 } else if (!strcmp(args[1], "show-legends")) {
4408 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4409 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4410 err_code |= ERR_ALERT | ERR_ABORT;
4411 goto out;
4412 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004413 } else if (!strcmp(args[1], "show-node")) {
4414
4415 if (*args[2]) {
4416 int i;
4417 char c;
4418
4419 for (i=0; args[2][i]; i++) {
4420 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004421 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4422 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004423 break;
4424 }
4425
4426 if (!i || args[2][i]) {
4427 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4428 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4429 file, linenum, args[0], args[1]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433 }
4434
4435 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4436 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4437 err_code |= ERR_ALERT | ERR_ABORT;
4438 goto out;
4439 }
4440 } else if (!strcmp(args[1], "show-desc")) {
4441 char *desc = NULL;
4442
4443 if (*args[2]) {
4444 int i, len=0;
4445 char *d;
4446
Willy Tarreau348acfe2014-04-14 15:00:39 +02004447 for (i = 2; *args[i]; i++)
4448 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004449
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004450 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004451
Willy Tarreau348acfe2014-04-14 15:00:39 +02004452 d += snprintf(d, desc + len - d, "%s", args[2]);
4453 for (i = 3; *args[i]; i++)
4454 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004455 }
4456
4457 if (!*args[2] && !global.desc)
4458 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4459 file, linenum, args[1]);
4460 else {
4461 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4462 free(desc);
4463 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4464 err_code |= ERR_ALERT | ERR_ABORT;
4465 goto out;
4466 }
4467 free(desc);
4468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004470stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004471 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 +01004472 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
4476 }
4477 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004478 int optnum;
4479
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004480 if (*(args[1]) == '\0') {
4481 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004486
4487 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4488 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004489 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4490 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4491 file, linenum, cfg_opts[optnum].name);
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004495 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4496 goto out;
4497
Willy Tarreau93893792009-07-23 13:19:11 +02004498 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4499 err_code |= ERR_WARN;
4500 goto out;
4501 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004502
Willy Tarreau3842f002009-06-14 11:39:52 +02004503 curproxy->no_options &= ~cfg_opts[optnum].val;
4504 curproxy->options &= ~cfg_opts[optnum].val;
4505
4506 switch (kwm) {
4507 case KWM_STD:
4508 curproxy->options |= cfg_opts[optnum].val;
4509 break;
4510 case KWM_NO:
4511 curproxy->no_options |= cfg_opts[optnum].val;
4512 break;
4513 case KWM_DEF: /* already cleared */
4514 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004515 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004516
Willy Tarreau93893792009-07-23 13:19:11 +02004517 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004518 }
4519 }
4520
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004521 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4522 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004523 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4524 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4525 file, linenum, cfg_opts2[optnum].name);
4526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
4528 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004529 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4530 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004531 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4532 err_code |= ERR_WARN;
4533 goto out;
4534 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004535
Willy Tarreau3842f002009-06-14 11:39:52 +02004536 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4537 curproxy->options2 &= ~cfg_opts2[optnum].val;
4538
4539 switch (kwm) {
4540 case KWM_STD:
4541 curproxy->options2 |= cfg_opts2[optnum].val;
4542 break;
4543 case KWM_NO:
4544 curproxy->no_options2 |= cfg_opts2[optnum].val;
4545 break;
4546 case KWM_DEF: /* already cleared */
4547 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004548 }
Willy Tarreau93893792009-07-23 13:19:11 +02004549 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004550 }
4551 }
4552
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004553 /* HTTP options override each other. They can be cancelled using
4554 * "no option xxx" which only switches to default mode if the mode
4555 * was this one (useful for cancelling options set in defaults
4556 * sections).
4557 */
4558 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004559 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4560 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004561 if (kwm == KWM_STD) {
4562 curproxy->options &= ~PR_O_HTTP_MODE;
4563 curproxy->options |= PR_O_HTTP_PCL;
4564 goto out;
4565 }
4566 else if (kwm == KWM_NO) {
4567 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4568 curproxy->options &= ~PR_O_HTTP_MODE;
4569 goto out;
4570 }
4571 }
4572 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004573 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4574 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004575 if (kwm == KWM_STD) {
4576 curproxy->options &= ~PR_O_HTTP_MODE;
4577 curproxy->options |= PR_O_HTTP_FCL;
4578 goto out;
4579 }
4580 else if (kwm == KWM_NO) {
4581 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4582 curproxy->options &= ~PR_O_HTTP_MODE;
4583 goto out;
4584 }
4585 }
4586 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004587 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4588 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004589 if (kwm == KWM_STD) {
4590 curproxy->options &= ~PR_O_HTTP_MODE;
4591 curproxy->options |= PR_O_HTTP_SCL;
4592 goto out;
4593 }
4594 else if (kwm == KWM_NO) {
4595 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4596 curproxy->options &= ~PR_O_HTTP_MODE;
4597 goto out;
4598 }
4599 }
4600 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004601 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4602 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004603 if (kwm == KWM_STD) {
4604 curproxy->options &= ~PR_O_HTTP_MODE;
4605 curproxy->options |= PR_O_HTTP_KAL;
4606 goto out;
4607 }
4608 else if (kwm == KWM_NO) {
4609 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4610 curproxy->options &= ~PR_O_HTTP_MODE;
4611 goto out;
4612 }
4613 }
4614 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004615 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4616 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004617 if (kwm == KWM_STD) {
4618 curproxy->options &= ~PR_O_HTTP_MODE;
4619 curproxy->options |= PR_O_HTTP_TUN;
4620 goto out;
4621 }
4622 else if (kwm == KWM_NO) {
4623 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4624 curproxy->options &= ~PR_O_HTTP_MODE;
4625 goto out;
4626 }
4627 }
4628
Joseph Lynch726ab712015-05-11 23:25:34 -07004629 /* Redispatch can take an integer argument that control when the
4630 * resispatch occurs. All values are relative to the retries option.
4631 * This can be cancelled using "no option xxx".
4632 */
4633 if (strcmp(args[1], "redispatch") == 0) {
4634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4635 err_code |= ERR_WARN;
4636 goto out;
4637 }
4638
4639 curproxy->no_options &= ~PR_O_REDISP;
4640 curproxy->options &= ~PR_O_REDISP;
4641
4642 switch (kwm) {
4643 case KWM_STD:
4644 curproxy->options |= PR_O_REDISP;
4645 curproxy->redispatch_after = -1;
4646 if(*args[2]) {
4647 curproxy->redispatch_after = atol(args[2]);
4648 }
4649 break;
4650 case KWM_NO:
4651 curproxy->no_options |= PR_O_REDISP;
4652 curproxy->redispatch_after = 0;
4653 break;
4654 case KWM_DEF: /* already cleared */
4655 break;
4656 }
4657 goto out;
4658 }
4659
Willy Tarreau3842f002009-06-14 11:39:52 +02004660 if (kwm != KWM_STD) {
4661 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004662 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004665 }
4666
Emeric Brun3a058f32009-06-30 18:26:00 +02004667 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004668 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004670 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004671 if (*(args[2]) != '\0') {
4672 if (!strcmp(args[2], "clf")) {
4673 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004674 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004675 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004676 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004679 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004680 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4681 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004682 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004683 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4684 char *oldlogformat = "log-format";
4685 char *clflogformat = "";
4686
4687 if (curproxy->conf.logformat_string == default_http_log_format)
4688 oldlogformat = "option httplog";
4689 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4690 oldlogformat = "option tcplog";
4691 else if (curproxy->conf.logformat_string == clf_http_log_format)
4692 oldlogformat = "option httplog clf";
4693 if (logformat == clf_http_log_format)
4694 clflogformat = " clf";
4695 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4696 file, linenum, clflogformat, oldlogformat);
4697 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004698 if (curproxy->conf.logformat_string != default_http_log_format &&
4699 curproxy->conf.logformat_string != default_tcp_log_format &&
4700 curproxy->conf.logformat_string != clf_http_log_format)
4701 free(curproxy->conf.logformat_string);
4702 curproxy->conf.logformat_string = logformat;
4703
4704 free(curproxy->conf.lfs_file);
4705 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4706 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004707 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004708 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004709 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4710 char *oldlogformat = "log-format";
4711
4712 if (curproxy->conf.logformat_string == default_http_log_format)
4713 oldlogformat = "option httplog";
4714 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4715 oldlogformat = "option tcplog";
4716 else if (curproxy->conf.logformat_string == clf_http_log_format)
4717 oldlogformat = "option httplog clf";
4718 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4719 file, linenum, oldlogformat);
4720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004722 if (curproxy->conf.logformat_string != default_http_log_format &&
4723 curproxy->conf.logformat_string != default_tcp_log_format &&
4724 curproxy->conf.logformat_string != clf_http_log_format)
4725 free(curproxy->conf.logformat_string);
4726 curproxy->conf.logformat_string = default_tcp_log_format;
4727
4728 free(curproxy->conf.lfs_file);
4729 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4730 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004731
4732 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4733 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004736 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004737 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004739
William Lallemanddf1425a2015-04-28 20:17:49 +02004740 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4741 goto out;
4742
Willy Tarreau13943ab2006-12-31 00:24:10 +01004743 if (curproxy->cap & PR_CAP_FE)
4744 curproxy->options |= PR_O_TCP_CLI_KA;
4745 if (curproxy->cap & PR_CAP_BE)
4746 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 }
4748 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_WARN;
4751
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004753 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004755 curproxy->options2 &= ~PR_O2_CHK_ANY;
4756 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 if (!*args[2]) { /* no argument */
4758 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4759 curproxy->check_len = strlen(DEF_CHECK_REQ);
4760 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004761 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004762 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004764 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004766 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 if (*args[4])
4768 reqlen += strlen(args[4]);
4769 else
4770 reqlen += strlen("HTTP/1.0");
4771
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004772 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004774 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004776 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4777 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004778 }
4779 else if (!strcmp(args[1], "ssl-hello-chk")) {
4780 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004781 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004782 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004783
Willy Tarreaua534fea2008-08-03 12:19:50 +02004784 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004785 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004786 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004787 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004788
4789 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 }
Willy Tarreau23677902007-05-08 23:50:35 +02004792 else if (!strcmp(args[1], "smtpchk")) {
4793 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004794 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004795 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004796 curproxy->options2 &= ~PR_O2_CHK_ANY;
4797 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004798
4799 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4800 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4801 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4802 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4803 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4804 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004805 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004806 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4807 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4808 } else {
4809 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4810 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4811 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4812 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4813 }
4814 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004815 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4816 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004817 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004818 else if (!strcmp(args[1], "pgsql-check")) {
4819 /* use PostgreSQL request to check servers' health */
4820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4821 err_code |= ERR_WARN;
4822
4823 free(curproxy->check_req);
4824 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004825 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004826 curproxy->options2 |= PR_O2_PGSQL_CHK;
4827
4828 if (*(args[2])) {
4829 int cur_arg = 2;
4830
4831 while (*(args[cur_arg])) {
4832 if (strcmp(args[cur_arg], "user") == 0) {
4833 char * packet;
4834 uint32_t packet_len;
4835 uint32_t pv;
4836
4837 /* suboption header - needs additional argument for it */
4838 if (*(args[cur_arg+1]) == 0) {
4839 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4840 file, linenum, args[0], args[1], args[cur_arg]);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
4844
4845 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4846 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4847 pv = htonl(0x30000); /* protocol version 3.0 */
4848
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004849 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004850
4851 memcpy(packet + 4, &pv, 4);
4852
4853 /* copy "user" */
4854 memcpy(packet + 8, "user", 4);
4855
4856 /* copy username */
4857 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4858
4859 free(curproxy->check_req);
4860 curproxy->check_req = packet;
4861 curproxy->check_len = packet_len;
4862
4863 packet_len = htonl(packet_len);
4864 memcpy(packet, &packet_len, 4);
4865 cur_arg += 2;
4866 } else {
4867 /* unknown suboption - catchall */
4868 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4869 file, linenum, args[0], args[1]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873 } /* end while loop */
4874 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004875 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4876 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004877 }
4878
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004879 else if (!strcmp(args[1], "redis-check")) {
4880 /* use REDIS PING request to check servers' health */
4881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4882 err_code |= ERR_WARN;
4883
4884 free(curproxy->check_req);
4885 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004886 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004887 curproxy->options2 |= PR_O2_REDIS_CHK;
4888
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004889 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004890 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4891 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004892
4893 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4894 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004895 }
4896
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004897 else if (!strcmp(args[1], "mysql-check")) {
4898 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4900 err_code |= ERR_WARN;
4901
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004902 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004903 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004904 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004905 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004906
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004907 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004908 * const char mysql40_client_auth_pkt[] = {
4909 * "\x0e\x00\x00" // packet length
4910 * "\x01" // packet number
4911 * "\x00\x00" // client capabilities
4912 * "\x00\x00\x01" // max packet
4913 * "haproxy\x00" // username (null terminated string)
4914 * "\x00" // filler (always 0x00)
4915 * "\x01\x00\x00" // packet length
4916 * "\x00" // packet number
4917 * "\x01" // COM_QUIT command
4918 * };
4919 */
4920
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004921 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4922 * const char mysql41_client_auth_pkt[] = {
4923 * "\x0e\x00\x00\" // packet length
4924 * "\x01" // packet number
4925 * "\x00\x00\x00\x00" // client capabilities
4926 * "\x00\x00\x00\x01" // max packet
4927 * "\x21" // character set (UTF-8)
4928 * char[23] // All zeroes
4929 * "haproxy\x00" // username (null terminated string)
4930 * "\x00" // filler (always 0x00)
4931 * "\x01\x00\x00" // packet length
4932 * "\x00" // packet number
4933 * "\x01" // COM_QUIT command
4934 * };
4935 */
4936
4937
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004938 if (*(args[2])) {
4939 int cur_arg = 2;
4940
4941 while (*(args[cur_arg])) {
4942 if (strcmp(args[cur_arg], "user") == 0) {
4943 char *mysqluser;
4944 int packetlen, reqlen, userlen;
4945
4946 /* suboption header - needs additional argument for it */
4947 if (*(args[cur_arg+1]) == 0) {
4948 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4949 file, linenum, args[0], args[1], args[cur_arg]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953 mysqluser = args[cur_arg + 1];
4954 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004955
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004956 if (*(args[cur_arg+2])) {
4957 if (!strcmp(args[cur_arg+2], "post-41")) {
4958 packetlen = userlen + 7 + 27;
4959 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004960
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004961 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004962 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004963 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004964
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004965 snprintf(curproxy->check_req, 4, "%c%c%c",
4966 ((unsigned char) packetlen & 0xff),
4967 ((unsigned char) (packetlen >> 8) & 0xff),
4968 ((unsigned char) (packetlen >> 16) & 0xff));
4969
4970 curproxy->check_req[3] = 1;
4971 curproxy->check_req[5] = 130;
4972 curproxy->check_req[11] = 1;
4973 curproxy->check_req[12] = 33;
4974 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4975 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4976 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4977 cur_arg += 3;
4978 } else {
4979 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
4983 } else {
4984 packetlen = userlen + 7;
4985 reqlen = packetlen + 9;
4986
4987 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004988 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004989 curproxy->check_len = reqlen;
4990
4991 snprintf(curproxy->check_req, 4, "%c%c%c",
4992 ((unsigned char) packetlen & 0xff),
4993 ((unsigned char) (packetlen >> 8) & 0xff),
4994 ((unsigned char) (packetlen >> 16) & 0xff));
4995
4996 curproxy->check_req[3] = 1;
4997 curproxy->check_req[5] = 128;
4998 curproxy->check_req[8] = 1;
4999 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5000 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5001 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5002 cur_arg += 2;
5003 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005004 } else {
5005 /* unknown suboption - catchall */
5006 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5007 file, linenum, args[0], args[1]);
5008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
5011 } /* end while loop */
5012 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005013 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005014 else if (!strcmp(args[1], "ldap-check")) {
5015 /* use LDAP request to check servers' health */
5016 free(curproxy->check_req);
5017 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005018 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005019 curproxy->options2 |= PR_O2_LDAP_CHK;
5020
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005021 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005022 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5023 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005024 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5025 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005026 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005027 else if (!strcmp(args[1], "spop-check")) {
5028 if (curproxy == &defproxy) {
5029 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5030 file, linenum, args[0], args[1]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
5034 if (curproxy->cap & PR_CAP_FE) {
5035 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5036 file, linenum, args[0], args[1]);
5037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039 }
5040
5041 /* use SPOE request to check servers' health */
5042 free(curproxy->check_req);
5043 curproxy->check_req = NULL;
5044 curproxy->options2 &= ~PR_O2_CHK_ANY;
5045 curproxy->options2 |= PR_O2_SPOP_CHK;
5046
Christopher Faulet8ef75252017-02-20 22:56:03 +01005047 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005048 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
5051 }
5052 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5053 goto out;
5054 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005055 else if (!strcmp(args[1], "tcp-check")) {
5056 /* use raw TCPCHK send/expect to check servers' health */
5057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5058 err_code |= ERR_WARN;
5059
5060 free(curproxy->check_req);
5061 curproxy->check_req = NULL;
5062 curproxy->options2 &= ~PR_O2_CHK_ANY;
5063 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005064 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5065 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005066 }
Simon Horman98637e52014-06-20 12:30:16 +09005067 else if (!strcmp(args[1], "external-check")) {
5068 /* excute an external command to check servers' health */
5069 free(curproxy->check_req);
5070 curproxy->check_req = NULL;
5071 curproxy->options2 &= ~PR_O2_CHK_ANY;
5072 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005073 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5074 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005075 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005076 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005077 int cur_arg;
5078
5079 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5080 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005081 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005082
Willy Tarreau87cf5142011-08-19 22:57:24 +02005083 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005084
5085 free(curproxy->fwdfor_hdr_name);
5086 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5087 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5088
5089 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5090 cur_arg = 2;
5091 while (*(args[cur_arg])) {
5092 if (!strcmp(args[cur_arg], "except")) {
5093 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005094 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005095 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5096 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005099 }
5100 /* flush useless bits */
5101 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005102 cur_arg += 2;
5103 } else if (!strcmp(args[cur_arg], "header")) {
5104 /* suboption header - needs additional argument for it */
5105 if (*(args[cur_arg+1]) == 0) {
5106 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5107 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005110 }
5111 free(curproxy->fwdfor_hdr_name);
5112 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5113 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5114 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005115 } else if (!strcmp(args[cur_arg], "if-none")) {
5116 curproxy->options &= ~PR_O_FF_ALWAYS;
5117 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005118 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005119 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005120 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005121 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005124 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005125 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005126 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005127 else if (!strcmp(args[1], "originalto")) {
5128 int cur_arg;
5129
5130 /* insert x-original-to field, but not for the IP address listed as an except.
5131 * set default options (ie: bitfield, header name, etc)
5132 */
5133
5134 curproxy->options |= PR_O_ORGTO;
5135
5136 free(curproxy->orgto_hdr_name);
5137 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5138 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5139
Willy Tarreau87cf5142011-08-19 22:57:24 +02005140 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005141 cur_arg = 2;
5142 while (*(args[cur_arg])) {
5143 if (!strcmp(args[cur_arg], "except")) {
5144 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005145 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 +02005146 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5147 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005150 }
5151 /* flush useless bits */
5152 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5153 cur_arg += 2;
5154 } else if (!strcmp(args[cur_arg], "header")) {
5155 /* suboption header - needs additional argument for it */
5156 if (*(args[cur_arg+1]) == 0) {
5157 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5158 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005161 }
5162 free(curproxy->orgto_hdr_name);
5163 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5164 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5165 cur_arg += 2;
5166 } else {
5167 /* unknown suboption - catchall */
5168 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5169 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005172 }
5173 } /* end while loop */
5174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 else {
5176 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005182 else if (!strcmp(args[0], "default_backend")) {
5183 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005184 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005185
5186 if (*(args[1]) == 0) {
5187 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005190 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005191 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005192 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005193
5194 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5195 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005198 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005200
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005201 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5202 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 +01005203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 /* enable reconnections to dispatch */
5206 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005207
5208 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005211 else if (!strcmp(args[0], "http-reuse")) {
5212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5213 err_code |= ERR_WARN;
5214
5215 if (strcmp(args[1], "never") == 0) {
5216 /* enable a graceful server shutdown on an HTTP 404 response */
5217 curproxy->options &= ~PR_O_REUSE_MASK;
5218 curproxy->options |= PR_O_REUSE_NEVR;
5219 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5220 goto out;
5221 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005222 else if (strcmp(args[1], "safe") == 0) {
5223 /* enable a graceful server shutdown on an HTTP 404 response */
5224 curproxy->options &= ~PR_O_REUSE_MASK;
5225 curproxy->options |= PR_O_REUSE_SAFE;
5226 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5227 goto out;
5228 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005229 else if (strcmp(args[1], "aggressive") == 0) {
5230 curproxy->options &= ~PR_O_REUSE_MASK;
5231 curproxy->options |= PR_O_REUSE_AGGR;
5232 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5233 goto out;
5234 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005235 else if (strcmp(args[1], "always") == 0) {
5236 /* enable a graceful server shutdown on an HTTP 404 response */
5237 curproxy->options &= ~PR_O_REUSE_MASK;
5238 curproxy->options |= PR_O_REUSE_ALWS;
5239 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5240 goto out;
5241 }
5242 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005243 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005248 else if (!strcmp(args[0], "http-check")) {
5249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005251
5252 if (strcmp(args[1], "disable-on-404") == 0) {
5253 /* enable a graceful server shutdown on an HTTP 404 response */
5254 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005255 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5256 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005257 }
Willy Tarreauef781042010-01-27 11:53:01 +01005258 else if (strcmp(args[1], "send-state") == 0) {
5259 /* enable emission of the apparent state of a server in HTTP checks */
5260 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005261 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5262 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005263 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005264 else if (strcmp(args[1], "expect") == 0) {
5265 const char *ptr_arg;
5266 int cur_arg;
5267
5268 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5269 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273
5274 cur_arg = 2;
5275 /* consider exclamation marks, sole or at the beginning of a word */
5276 while (*(ptr_arg = args[cur_arg])) {
5277 while (*ptr_arg == '!') {
5278 curproxy->options2 ^= PR_O2_EXP_INV;
5279 ptr_arg++;
5280 }
5281 if (*ptr_arg)
5282 break;
5283 cur_arg++;
5284 }
5285 /* now ptr_arg points to the beginning of a word past any possible
5286 * exclamation mark, and cur_arg is the argument which holds this word.
5287 */
5288 if (strcmp(ptr_arg, "status") == 0) {
5289 if (!*(args[cur_arg + 1])) {
5290 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5291 file, linenum, args[0], args[1], ptr_arg);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
5295 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005296 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005297 curproxy->expect_str = strdup(args[cur_arg + 1]);
5298 }
5299 else if (strcmp(ptr_arg, "string") == 0) {
5300 if (!*(args[cur_arg + 1])) {
5301 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5302 file, linenum, args[0], args[1], ptr_arg);
5303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
5305 }
5306 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005307 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005308 curproxy->expect_str = strdup(args[cur_arg + 1]);
5309 }
5310 else if (strcmp(ptr_arg, "rstatus") == 0) {
5311 if (!*(args[cur_arg + 1])) {
5312 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5313 file, linenum, args[0], args[1], ptr_arg);
5314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
5316 }
5317 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005318 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005319 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005320 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005321 free(curproxy->expect_regex);
5322 curproxy->expect_regex = NULL;
5323 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005324 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005325 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5326 error = NULL;
5327 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5328 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5329 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5330 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
5333 }
5334 }
5335 else if (strcmp(ptr_arg, "rstring") == 0) {
5336 if (!*(args[cur_arg + 1])) {
5337 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5338 file, linenum, args[0], args[1], ptr_arg);
5339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
5341 }
5342 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005343 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005344 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005345 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005346 free(curproxy->expect_regex);
5347 curproxy->expect_regex = NULL;
5348 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005349 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005350 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5351 error = NULL;
5352 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5353 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5354 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5355 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359 }
5360 else {
5361 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5362 file, linenum, args[0], args[1], ptr_arg);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005367 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005368 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 +02005369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005371 }
5372 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005373 else if (!strcmp(args[0], "tcp-check")) {
5374 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5375 err_code |= ERR_WARN;
5376
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005377 if (strcmp(args[1], "comment") == 0) {
5378 int cur_arg;
5379 struct tcpcheck_rule *tcpcheck;
5380
5381 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005382 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005383 tcpcheck->action = TCPCHK_ACT_COMMENT;
5384
5385 if (!*args[cur_arg + 1]) {
5386 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5387 file, linenum, args[cur_arg]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391
5392 tcpcheck->comment = strdup(args[cur_arg + 1]);
5393
5394 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005395 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5396 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005397 }
5398 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005399 const char *ptr_arg;
5400 int cur_arg;
5401 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005402
5403 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005404 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5405 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5406 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5407 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5408 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005409
Willy Tarreau5581c272015-05-13 12:24:53 +02005410 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5411 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5412 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5413 file, linenum);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005416 }
5417
5418 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005419 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005420 tcpcheck->action = TCPCHK_ACT_CONNECT;
5421
5422 /* parsing each parameters to fill up the rule */
5423 while (*(ptr_arg = args[cur_arg])) {
5424 /* tcp port */
5425 if (strcmp(args[cur_arg], "port") == 0) {
5426 if ( (atol(args[cur_arg + 1]) > 65535) ||
5427 (atol(args[cur_arg + 1]) < 1) ){
5428 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5429 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433 tcpcheck->port = atol(args[cur_arg + 1]);
5434 cur_arg += 2;
5435 }
5436 /* send proxy protocol */
5437 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5438 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5439 cur_arg++;
5440 }
5441#ifdef USE_OPENSSL
5442 else if (strcmp(args[cur_arg], "ssl") == 0) {
5443 curproxy->options |= PR_O_TCPCHK_SSL;
5444 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5445 cur_arg++;
5446 }
5447#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005448 /* comment for this tcpcheck line */
5449 else if (strcmp(args[cur_arg], "comment") == 0) {
5450 if (!*args[cur_arg + 1]) {
5451 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5452 file, linenum, args[cur_arg]);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
5456 tcpcheck->comment = strdup(args[cur_arg + 1]);
5457 cur_arg += 2;
5458 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005459 else {
5460#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005461 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 +01005462#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005463 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 +01005464#endif /* USE_OPENSSL */
5465 file, linenum, args[0], args[1], args[cur_arg]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
5469
5470 }
5471
5472 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5473 }
5474 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005475 if (! *(args[2]) ) {
5476 /* SEND string expected */
5477 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5478 file, linenum, args[0], args[1], args[2]);
5479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
5481 } else {
5482 struct tcpcheck_rule *tcpcheck;
5483
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005484 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005485
5486 tcpcheck->action = TCPCHK_ACT_SEND;
5487 tcpcheck->string_len = strlen(args[2]);
5488 tcpcheck->string = strdup(args[2]);
5489 tcpcheck->expect_regex = NULL;
5490
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005491 /* comment for this tcpcheck line */
5492 if (strcmp(args[3], "comment") == 0) {
5493 if (!*args[4]) {
5494 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5495 file, linenum, args[3]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499 tcpcheck->comment = strdup(args[4]);
5500 }
5501
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005502 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5503 }
5504 }
5505 else if (strcmp(args[1], "send-binary") == 0) {
5506 if (! *(args[2]) ) {
5507 /* SEND binary string expected */
5508 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5509 file, linenum, args[0], args[1], args[2]);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 } else {
5513 struct tcpcheck_rule *tcpcheck;
5514 char *err = NULL;
5515
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005516 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005517
5518 tcpcheck->action = TCPCHK_ACT_SEND;
5519 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5520 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5521 file, linenum, args[0], args[1], args[2], err);
5522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
5524 }
5525 tcpcheck->expect_regex = NULL;
5526
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005527 /* comment for this tcpcheck line */
5528 if (strcmp(args[3], "comment") == 0) {
5529 if (!*args[4]) {
5530 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5531 file, linenum, args[3]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535 tcpcheck->comment = strdup(args[4]);
5536 }
5537
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005538 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5539 }
5540 }
5541 else if (strcmp(args[1], "expect") == 0) {
5542 const char *ptr_arg;
5543 int cur_arg;
5544 int inverse = 0;
5545
5546 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5547 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551
5552 cur_arg = 2;
5553 /* consider exclamation marks, sole or at the beginning of a word */
5554 while (*(ptr_arg = args[cur_arg])) {
5555 while (*ptr_arg == '!') {
5556 inverse = !inverse;
5557 ptr_arg++;
5558 }
5559 if (*ptr_arg)
5560 break;
5561 cur_arg++;
5562 }
5563 /* now ptr_arg points to the beginning of a word past any possible
5564 * exclamation mark, and cur_arg is the argument which holds this word.
5565 */
5566 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005567 struct tcpcheck_rule *tcpcheck;
5568 char *err = NULL;
5569
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005570 if (!*(args[cur_arg + 1])) {
5571 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5572 file, linenum, args[0], args[1], ptr_arg);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005576
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005577 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578
5579 tcpcheck->action = TCPCHK_ACT_EXPECT;
5580 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5581 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5582 file, linenum, args[0], args[1], args[2], err);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586 tcpcheck->expect_regex = NULL;
5587 tcpcheck->inverse = inverse;
5588
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005589 /* tcpcheck comment */
5590 cur_arg += 2;
5591 if (strcmp(args[cur_arg], "comment") == 0) {
5592 if (!*args[cur_arg + 1]) {
5593 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5594 file, linenum, args[cur_arg + 1]);
5595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
5597 }
5598 tcpcheck->comment = strdup(args[cur_arg + 1]);
5599 }
5600
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005601 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5602 }
5603 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005604 struct tcpcheck_rule *tcpcheck;
5605
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005606 if (!*(args[cur_arg + 1])) {
5607 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5608 file, linenum, args[0], args[1], ptr_arg);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005613 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005614
5615 tcpcheck->action = TCPCHK_ACT_EXPECT;
5616 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5617 tcpcheck->string = strdup(args[cur_arg + 1]);
5618 tcpcheck->expect_regex = NULL;
5619 tcpcheck->inverse = inverse;
5620
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005621 /* tcpcheck comment */
5622 cur_arg += 2;
5623 if (strcmp(args[cur_arg], "comment") == 0) {
5624 if (!*args[cur_arg + 1]) {
5625 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5626 file, linenum, args[cur_arg + 1]);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
5630 tcpcheck->comment = strdup(args[cur_arg + 1]);
5631 }
5632
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005633 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5634 }
5635 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005636 struct tcpcheck_rule *tcpcheck;
5637
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005638 if (!*(args[cur_arg + 1])) {
5639 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5640 file, linenum, args[0], args[1], ptr_arg);
5641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
5643 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005644
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005645 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005646
5647 tcpcheck->action = TCPCHK_ACT_EXPECT;
5648 tcpcheck->string_len = 0;
5649 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005650 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5651 error = NULL;
5652 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5653 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5654 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5655 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659 tcpcheck->inverse = inverse;
5660
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005661 /* tcpcheck comment */
5662 cur_arg += 2;
5663 if (strcmp(args[cur_arg], "comment") == 0) {
5664 if (!*args[cur_arg + 1]) {
5665 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5666 file, linenum, args[cur_arg + 1]);
5667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
5669 }
5670 tcpcheck->comment = strdup(args[cur_arg + 1]);
5671 }
5672
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005673 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5674 }
5675 else {
5676 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5677 file, linenum, args[0], args[1], ptr_arg);
5678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
5680 }
5681 }
5682 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005683 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
5687 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005688 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005689 if (curproxy == &defproxy) {
5690 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005693 }
5694
Willy Tarreaub80c2302007-11-30 20:51:32 +01005695 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005696 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005697
5698 if (strcmp(args[1], "fail") == 0) {
5699 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005700 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005701 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5702 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005705 }
5706
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005707 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5708 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5709 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005712 }
5713 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5714 }
5715 else {
5716 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005719 }
5720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721#ifdef TPROXY
5722 else if (!strcmp(args[0], "transparent")) {
5723 /* enable transparent proxy connections */
5724 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005725 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728#endif
5729 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005730 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 if (*(args[1]) == 0) {
5734 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 }
5738 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005739 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005742 else if (!strcmp(args[0], "backlog")) { /* backlog */
5743 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005744 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005745
5746 if (*(args[1]) == 0) {
5747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005750 }
5751 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005752 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5753 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005754 }
Willy Tarreau86034312006-12-29 00:10:33 +01005755 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005758
Willy Tarreau86034312006-12-29 00:10:33 +01005759 if (*(args[1]) == 0) {
5760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005763 }
5764 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005765 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5766 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5769 if (*(args[1]) == 0) {
5770 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005774 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5775 if (err) {
5776 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5777 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005780 }
5781 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005782 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005786 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005787 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005788 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005789
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 if (curproxy == &defproxy) {
5791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005795 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005797
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005798 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005799 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005800 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005801 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005802 goto out;
5803 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005804
5805 proto = protocol_by_family(sk->ss_family);
5806 if (!proto || !proto->connect) {
5807 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5808 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005809 err_code |= ERR_ALERT | ERR_FATAL;
5810 goto out;
5811 }
5812
5813 if (port1 != port2) {
5814 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5815 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005819
5820 if (!port1) {
5821 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5822 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
5825 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005826
William Lallemanddf1425a2015-04-28 20:17:49 +02005827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5828 goto out;
5829
Willy Tarreaud5191e72010-02-09 20:50:45 +01005830 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005831 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005836
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005837 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5838 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005843 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844 /**
5845 * The syntax for hash-type config element is
5846 * hash-type {map-based|consistent} [[<algo>] avalanche]
5847 *
5848 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5849 */
5850 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005851
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5853 err_code |= ERR_WARN;
5854
5855 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005856 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5857 }
5858 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005859 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5860 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005861 else if (strcmp(args[1], "avalanche") == 0) {
5862 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]);
5863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005865 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005866 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005867 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
Bhaskar98634f02013-10-29 23:30:51 -04005871
5872 /* set the hash function to use */
5873 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005874 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005875 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005876
5877 /* if consistent with no argument, then avalanche modifier is also applied */
5878 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5879 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005880 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005881 /* set the hash function */
5882 if (!strcmp(args[2], "sdbm")) {
5883 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5884 }
5885 else if (!strcmp(args[2], "djb2")) {
5886 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005887 }
5888 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005889 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005890 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005891 else if (!strcmp(args[2], "crc32")) {
5892 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5893 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005894 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005895 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 -05005896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
5899
5900 /* set the hash modifier */
5901 if (!strcmp(args[3], "avalanche")) {
5902 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5903 }
5904 else if (*args[3]) {
5905 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5906 err_code |= ERR_ALERT | ERR_FATAL;
5907 goto out;
5908 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005909 }
William Lallemanda73203e2012-03-12 12:48:57 +01005910 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005911 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5912 if (*(args[1]) == 0) {
5913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
5916 }
5917 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5918 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5919 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
5922 }
5923 }
William Lallemanda73203e2012-03-12 12:48:57 +01005924 else if (strcmp(args[0], "unique-id-format") == 0) {
5925 if (!*(args[1])) {
5926 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
5929 }
William Lallemand3203ff42012-11-11 17:30:56 +01005930 if (*(args[2])) {
5931 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5932 err_code |= ERR_ALERT | ERR_FATAL;
5933 goto out;
5934 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005935 free(curproxy->conf.uniqueid_format_string);
5936 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005937
Willy Tarreau62a61232013-04-12 18:13:46 +02005938 free(curproxy->conf.uif_file);
5939 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5940 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005941 }
William Lallemanda73203e2012-03-12 12:48:57 +01005942
5943 else if (strcmp(args[0], "unique-id-header") == 0) {
5944 if (!*(args[1])) {
5945 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5946 err_code |= ERR_ALERT | ERR_FATAL;
5947 goto out;
5948 }
5949 free(curproxy->header_unique_id);
5950 curproxy->header_unique_id = strdup(args[1]);
5951 }
5952
William Lallemand723b73a2012-02-08 16:37:49 +01005953 else if (strcmp(args[0], "log-format") == 0) {
5954 if (!*(args[1])) {
5955 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958 }
William Lallemand3203ff42012-11-11 17:30:56 +01005959 if (*(args[2])) {
5960 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5961 err_code |= ERR_ALERT | ERR_FATAL;
5962 goto out;
5963 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005964 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5965 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005966
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005967 if (curproxy->conf.logformat_string == default_http_log_format)
5968 oldlogformat = "option httplog";
5969 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5970 oldlogformat = "option tcplog";
5971 else if (curproxy->conf.logformat_string == clf_http_log_format)
5972 oldlogformat = "option httplog clf";
5973 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5974 file, linenum, oldlogformat);
5975 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005976 if (curproxy->conf.logformat_string != default_http_log_format &&
5977 curproxy->conf.logformat_string != default_tcp_log_format &&
5978 curproxy->conf.logformat_string != clf_http_log_format)
5979 free(curproxy->conf.logformat_string);
5980 curproxy->conf.logformat_string = strdup(args[1]);
5981
5982 free(curproxy->conf.lfs_file);
5983 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5984 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005985
5986 /* get a chance to improve log-format error reporting by
5987 * reporting the correct line-number when possible.
5988 */
5989 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5990 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5991 file, linenum, curproxy->id);
5992 err_code |= ERR_WARN;
5993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005995 else if (!strcmp(args[0], "log-format-sd")) {
5996 if (!*(args[1])) {
5997 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001 if (*(args[2])) {
6002 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006
6007 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6008 free(curproxy->conf.logformat_sd_string);
6009 curproxy->conf.logformat_sd_string = strdup(args[1]);
6010
6011 free(curproxy->conf.lfsd_file);
6012 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6013 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6014
6015 /* get a chance to improve log-format-sd error reporting by
6016 * reporting the correct line-number when possible.
6017 */
6018 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6019 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6020 file, linenum, curproxy->id);
6021 err_code |= ERR_WARN;
6022 }
6023 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006024 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6025 if (*(args[1]) == 0) {
6026 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006030 chunk_destroy(&curproxy->log_tag);
6031 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006032 }
William Lallemand0f99e342011-10-12 17:50:54 +02006033 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6034 /* delete previous herited or defined syslog servers */
6035 struct logsrv *back;
6036
6037 if (*(args[1]) != 0) {
6038 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
6041 }
6042
William Lallemand723b73a2012-02-08 16:37:49 +01006043 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6044 LIST_DEL(&tmplogsrv->list);
6045 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006046 }
6047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006049 struct logsrv *logsrv;
6050
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006052 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006053 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006054 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006055 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006056 LIST_INIT(&node->list);
6057 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
6060 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006061 struct sockaddr_storage *sk;
6062 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006063 int arg = 0;
6064 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006065
Vincent Bernat02779b62016-04-03 13:48:43 +02006066 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067
Willy Tarreau18324f52014-06-27 18:10:07 +02006068 /* just after the address, a length may be specified */
6069 if (strcmp(args[arg+2], "len") == 0) {
6070 len = atoi(args[arg+3]);
6071 if (len < 80 || len > 65535) {
6072 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6073 file, linenum, args[arg+3]);
6074 err_code |= ERR_ALERT | ERR_FATAL;
6075 goto out;
6076 }
6077 logsrv->maxlen = len;
6078
6079 /* skip these two args */
6080 arg += 2;
6081 }
6082 else
6083 logsrv->maxlen = MAX_SYSLOG_LEN;
6084
6085 if (logsrv->maxlen > global.max_syslog_len) {
6086 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006087 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6088 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6089 logline = my_realloc2(logline, global.max_syslog_len + 1);
6090 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006091 }
6092
Dragan Dosen1322d092015-09-22 16:05:32 +02006093 /* after the length, a format may be specified */
6094 if (strcmp(args[arg+2], "format") == 0) {
6095 logsrv->format = get_log_format(args[arg+3]);
6096 if (logsrv->format < 0) {
6097 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
6100 }
6101
6102 /* skip these two args */
6103 arg += 2;
6104 }
6105
William Lallemanddf1425a2015-04-28 20:17:49 +02006106 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6107 goto out;
6108
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006111 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
6114
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 }
6116
William Lallemand0f99e342011-10-12 17:50:54 +02006117 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006118 if (*(args[arg+3])) {
6119 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006120 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006121 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124
Willy Tarreaubaaee002006-06-26 02:48:02 +02006125 }
6126 }
6127
William Lallemand0f99e342011-10-12 17:50:54 +02006128 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006129 if (*(args[arg+4])) {
6130 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006131 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006132 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006136 }
6137 }
6138
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006139 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006141 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006142 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006143 goto out;
6144 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006145
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006146 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006147
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006148 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006149 if (port1 != port2) {
6150 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6151 file, linenum, args[0], args[1]);
6152 err_code |= ERR_ALERT | ERR_FATAL;
6153 goto out;
6154 }
6155
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006156 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006157 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 }
William Lallemand0f99e342011-10-12 17:50:54 +02006159
6160 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
6162 else {
6163 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 }
6168 }
6169 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006170 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006171 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006172 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006173 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006174
Willy Tarreau977b8e42006-12-29 14:19:17 +01006175 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006177
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006179 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6180 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006181 err_code |= ERR_ALERT | ERR_FATAL;
6182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006184
6185 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006186 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6187 free(curproxy->conn_src.iface_name);
6188 curproxy->conn_src.iface_name = NULL;
6189 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006190
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006191 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006192 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006194 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006195 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006196 goto out;
6197 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006198
6199 proto = protocol_by_family(sk->ss_family);
6200 if (!proto || !proto->connect) {
6201 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006202 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
6205 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006206
6207 if (port1 != port2) {
6208 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6209 file, linenum, args[0], args[1]);
6210 err_code |= ERR_ALERT | ERR_FATAL;
6211 goto out;
6212 }
6213
Willy Tarreauef9a3602012-12-08 22:29:20 +01006214 curproxy->conn_src.source_addr = *sk;
6215 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006216
6217 cur_arg = 2;
6218 while (*(args[cur_arg])) {
6219 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006220#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006221 if (!*args[cur_arg + 1]) {
6222 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6223 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006226 }
6227
6228 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006229 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6230 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006231 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006232 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6233 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006234 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6235 char *name, *end;
6236
6237 name = args[cur_arg+1] + 7;
6238 while (isspace(*name))
6239 name++;
6240
6241 end = name;
6242 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6243 end++;
6244
Willy Tarreauef9a3602012-12-08 22:29:20 +01006245 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6246 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6247 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6248 curproxy->conn_src.bind_hdr_len = end - name;
6249 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6250 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6251 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006252
6253 /* now look for an occurrence number */
6254 while (isspace(*end))
6255 end++;
6256 if (*end == ',') {
6257 end++;
6258 name = end;
6259 if (*end == '-')
6260 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006261 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006262 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006263 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006264 }
6265
Willy Tarreauef9a3602012-12-08 22:29:20 +01006266 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006267 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6268 " occurrences values smaller than %d.\n",
6269 file, linenum, MAX_HDR_HISTORY);
6270 err_code |= ERR_ALERT | ERR_FATAL;
6271 goto out;
6272 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006274 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006275
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006276 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006277 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006279 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281 goto out;
6282 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006283
6284 proto = protocol_by_family(sk->ss_family);
6285 if (!proto || !proto->connect) {
6286 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6287 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
6290 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006291
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006292 if (port1 != port2) {
6293 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6294 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006295 err_code |= ERR_ALERT | ERR_FATAL;
6296 goto out;
6297 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006298 curproxy->conn_src.tproxy_addr = *sk;
6299 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300 }
6301 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302#else /* no TPROXY support */
6303 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006304 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006307#endif
6308 cur_arg += 2;
6309 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006310 }
6311
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006312 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6313#ifdef SO_BINDTODEVICE
6314 if (!*args[cur_arg + 1]) {
6315 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6316 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006317 err_code |= ERR_ALERT | ERR_FATAL;
6318 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006319 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006320 free(curproxy->conn_src.iface_name);
6321 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6322 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006323 global.last_checks |= LSTCHK_NETADM;
6324#else
6325 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6326 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006327 err_code |= ERR_ALERT | ERR_FATAL;
6328 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006329#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006330 cur_arg += 2;
6331 continue;
6332 }
6333 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006334 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006335 err_code |= ERR_ALERT | ERR_FATAL;
6336 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006339 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6340 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6341 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006342 err_code |= ERR_ALERT | ERR_FATAL;
6343 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006349 err_code |= ERR_ALERT | ERR_FATAL;
6350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352
6353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
6366 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
6373 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006375 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
6380 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006382 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006387 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006389 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006390 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006392 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006398 err_code |= ERR_ALERT | ERR_FATAL;
6399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401
6402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006403 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006404 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 }
6408 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006410 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 }
6415 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006417 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006418 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006419 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 }
6422 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006424 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006425 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006426 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
6429 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006431 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006432 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006433 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006436 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006438 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006439 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006441 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006444 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006445
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 if (curproxy == &defproxy) {
6447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006451 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006452 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 if (*(args[1]) == 0) {
6455 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006459
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006460 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006461 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6462 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6463 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006464 err_code |= ERR_ALERT | ERR_FATAL;
6465 goto out;
6466 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006467 err_code |= warnif_cond_conflicts(cond,
6468 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6469 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006470 }
6471 else if (*args[2]) {
6472 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6473 file, linenum, args[0], args[2]);
6474 err_code |= ERR_ALERT | ERR_FATAL;
6475 goto out;
6476 }
6477
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006478 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006479 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006480 wl->s = strdup(args[1]);
6481 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006482 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006491
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006493 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006494 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 }
6498 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006500 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
6505 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006507 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 }
6519
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006521 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006522 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006523 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525 }
6526 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006527 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006528 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006529 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006530 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532 }
6533 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006534 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006535 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006536 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006537 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 }
6540 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006541 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006542
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 if (curproxy == &defproxy) {
6544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006545 err_code |= ERR_ALERT | ERR_FATAL;
6546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006548 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006549 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 if (*(args[1]) == 0) {
6552 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006553 err_code |= ERR_ALERT | ERR_FATAL;
6554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 }
6556
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006557 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006558 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6559 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6560 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
6563 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006564 err_code |= warnif_cond_conflicts(cond,
6565 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6566 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006567 }
6568 else if (*args[2]) {
6569 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6570 file, linenum, args[0], args[2]);
6571 err_code |= ERR_ALERT | ERR_FATAL;
6572 goto out;
6573 }
6574
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006575 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006576 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006577 wl->s = strdup(args[1]);
6578 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 }
6580 else if (!strcmp(args[0], "errorloc") ||
6581 !strcmp(args[0], "errorloc302") ||
6582 !strcmp(args[0], "errorloc303")) { /* error location */
6583 int errnum, errlen;
6584 char *err;
6585
Willy Tarreau977b8e42006-12-29 14:19:17 +01006586 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006587 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006588
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006590 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
6592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 }
6594
6595 errnum = atol(args[1]);
6596 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006597 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6598 err = malloc(errlen);
6599 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006601 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6602 err = malloc(errlen);
6603 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 }
6605
Willy Tarreau0f772532006-12-23 20:51:41 +01006606 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6607 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006608 chunk_destroy(&curproxy->errmsg[rc]);
6609 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006610 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006613
6614 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006615 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6616 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 free(err);
6618 }
6619 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006620 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6621 int errnum, errlen, fd;
6622 char *err;
6623 struct stat stat;
6624
6625 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006626 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006627
6628 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006629 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006630 err_code |= ERR_ALERT | ERR_FATAL;
6631 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006632 }
6633
6634 fd = open(args[2], O_RDONLY);
6635 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6636 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6637 file, linenum, args[2], args[1]);
6638 if (fd >= 0)
6639 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006640 err_code |= ERR_ALERT | ERR_FATAL;
6641 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006642 }
6643
Willy Tarreau27a674e2009-08-17 07:23:33 +02006644 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006645 errlen = stat.st_size;
6646 } else {
6647 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006648 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006649 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006650 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006651 }
6652
6653 err = malloc(errlen); /* malloc() must succeed during parsing */
6654 errnum = read(fd, err, errlen);
6655 if (errnum != errlen) {
6656 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6657 file, linenum, args[2], args[1]);
6658 close(fd);
6659 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006660 err_code |= ERR_ALERT | ERR_FATAL;
6661 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006662 }
6663 close(fd);
6664
6665 errnum = atol(args[1]);
6666 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6667 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006668 chunk_destroy(&curproxy->errmsg[rc]);
6669 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006670 break;
6671 }
6672 }
6673
6674 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006675 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6676 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006677 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006678 free(err);
6679 }
6680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006682 struct cfg_kw_list *kwl;
6683 int index;
6684
6685 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6686 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6687 if (kwl->kw[index].section != CFG_LISTEN)
6688 continue;
6689 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6690 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006691 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006692 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006693 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006694 err_code |= ERR_ALERT | ERR_FATAL;
6695 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006696 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006697 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006698 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006699 err_code |= ERR_WARN;
6700 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006701 }
Willy Tarreau93893792009-07-23 13:19:11 +02006702 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006703 }
6704 }
6705 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006706
Willy Tarreau6daf3432008-01-22 16:44:08 +01006707 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006708 err_code |= ERR_ALERT | ERR_FATAL;
6709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 }
Willy Tarreau93893792009-07-23 13:19:11 +02006711 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006712 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006713 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714}
6715
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006716int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006717cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6718{
6719#ifdef CONFIG_HAP_NS
6720 const char *err;
6721 const char *item = args[0];
6722
6723 if (!strcmp(item, "namespace_list")) {
6724 return 0;
6725 }
6726 else if (!strcmp(item, "namespace")) {
6727 size_t idx = 1;
6728 const char *current;
6729 while (*(current = args[idx++])) {
6730 err = invalid_char(current);
6731 if (err) {
6732 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6733 file, linenum, *err, item, current);
6734 return ERR_ALERT | ERR_FATAL;
6735 }
6736
6737 if (netns_store_lookup(current, strlen(current))) {
6738 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6739 file, linenum, current);
6740 return ERR_ALERT | ERR_FATAL;
6741 }
6742 if (!netns_store_insert(current)) {
6743 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6744 file, linenum, current);
6745 return ERR_ALERT | ERR_FATAL;
6746 }
6747 }
6748 }
6749
6750 return 0;
6751#else
6752 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6753 file, linenum);
6754 return ERR_ALERT | ERR_FATAL;
6755#endif
6756}
6757
6758int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006759cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6760{
6761
6762 int err_code = 0;
6763 const char *err;
6764
6765 if (!strcmp(args[0], "userlist")) { /* new userlist */
6766 struct userlist *newul;
6767
6768 if (!*args[1]) {
6769 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6770 file, linenum, args[0]);
6771 err_code |= ERR_ALERT | ERR_FATAL;
6772 goto out;
6773 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006774 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6775 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776
6777 err = invalid_char(args[1]);
6778 if (err) {
6779 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6780 file, linenum, *err, args[0], args[1]);
6781 err_code |= ERR_ALERT | ERR_FATAL;
6782 goto out;
6783 }
6784
6785 for (newul = userlist; newul; newul = newul->next)
6786 if (!strcmp(newul->name, args[1])) {
6787 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6788 file, linenum, args[1]);
6789 err_code |= ERR_WARN;
6790 goto out;
6791 }
6792
Vincent Bernat02779b62016-04-03 13:48:43 +02006793 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 if (!newul) {
6795 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6796 err_code |= ERR_ALERT | ERR_ABORT;
6797 goto out;
6798 }
6799
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006801 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6803 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006804 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805 goto out;
6806 }
6807
6808 newul->next = userlist;
6809 userlist = newul;
6810
6811 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006814 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815
6816 if (!*args[1]) {
6817 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6818 file, linenum, args[0]);
6819 err_code |= ERR_ALERT | ERR_FATAL;
6820 goto out;
6821 }
6822
6823 err = invalid_char(args[1]);
6824 if (err) {
6825 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6826 file, linenum, *err, args[0], args[1]);
6827 err_code |= ERR_ALERT | ERR_FATAL;
6828 goto out;
6829 }
6830
William Lallemand4ac9f542015-05-28 18:03:51 +02006831 if (!userlist)
6832 goto out;
6833
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006834 for (ag = userlist->groups; ag; ag = ag->next)
6835 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006836 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6837 file, linenum, args[1], userlist->name);
6838 err_code |= ERR_ALERT;
6839 goto out;
6840 }
6841
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006842 ag = calloc(1, sizeof(*ag));
6843 if (!ag) {
6844 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6845 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846 goto out;
6847 }
6848
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006850 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6852 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006853 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006854 goto out;
6855 }
6856
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 cur_arg = 2;
6858
6859 while (*args[cur_arg]) {
6860 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006861 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 cur_arg += 2;
6863 continue;
6864 } else {
6865 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6866 file, linenum, args[0]);
6867 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006868 free(ag->groupusers);
6869 free(ag->name);
6870 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006871 goto out;
6872 }
6873 }
6874
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006875 ag->next = userlist->groups;
6876 userlist->groups = ag;
6877
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878 } else if (!strcmp(args[0], "user")) { /* new user */
6879 struct auth_users *newuser;
6880 int cur_arg;
6881
6882 if (!*args[1]) {
6883 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6884 file, linenum, args[0]);
6885 err_code |= ERR_ALERT | ERR_FATAL;
6886 goto out;
6887 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006888 if (!userlist)
6889 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006890
6891 for (newuser = userlist->users; newuser; newuser = newuser->next)
6892 if (!strcmp(newuser->user, args[1])) {
6893 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6894 file, linenum, args[1], userlist->name);
6895 err_code |= ERR_ALERT;
6896 goto out;
6897 }
6898
Vincent Bernat02779b62016-04-03 13:48:43 +02006899 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006900 if (!newuser) {
6901 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6902 err_code |= ERR_ALERT | ERR_ABORT;
6903 goto out;
6904 }
6905
6906 newuser->user = strdup(args[1]);
6907
6908 newuser->next = userlist->users;
6909 userlist->users = newuser;
6910
6911 cur_arg = 2;
6912
6913 while (*args[cur_arg]) {
6914 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006915#ifdef CONFIG_HAP_CRYPT
6916 if (!crypt("", args[cur_arg + 1])) {
6917 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6918 file, linenum, newuser->user);
6919 err_code |= ERR_ALERT | ERR_FATAL;
6920 goto out;
6921 }
6922#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006923 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6924 file, linenum);
6925 err_code |= ERR_ALERT;
6926#endif
6927 newuser->pass = strdup(args[cur_arg + 1]);
6928 cur_arg += 2;
6929 continue;
6930 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6931 newuser->pass = strdup(args[cur_arg + 1]);
6932 newuser->flags |= AU_O_INSECURE;
6933 cur_arg += 2;
6934 continue;
6935 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006936 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006937 cur_arg += 2;
6938 continue;
6939 } else {
6940 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6941 file, linenum, args[0]);
6942 err_code |= ERR_ALERT | ERR_FATAL;
6943 goto out;
6944 }
6945 }
6946 } else {
6947 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6948 err_code |= ERR_ALERT | ERR_FATAL;
6949 }
6950
6951out:
6952 return err_code;
6953}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954
Christopher Faulet79bdef32016-11-04 22:36:15 +01006955int
6956cfg_parse_scope(const char *file, int linenum, char *line)
6957{
6958 char *beg, *end, *scope = NULL;
6959 int err_code = 0;
6960 const char *err;
6961
6962 beg = line + 1;
6963 end = strchr(beg, ']');
6964
6965 /* Detect end of scope declaration */
6966 if (!end || end == beg) {
6967 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6968 file, linenum);
6969 err_code |= ERR_ALERT | ERR_FATAL;
6970 goto out;
6971 }
6972
6973 /* Get scope name and check its validity */
6974 scope = my_strndup(beg, end-beg);
6975 err = invalid_char(scope);
6976 if (err) {
6977 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6978 file, linenum, *err);
6979 err_code |= ERR_ALERT | ERR_ABORT;
6980 goto out;
6981 }
6982
6983 /* Be sure to have a scope declaration alone on its line */
6984 line = end+1;
6985 while (isspace((unsigned char)*line))
6986 line++;
6987 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6988 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6989 file, linenum, *line);
6990 err_code |= ERR_ALERT | ERR_ABORT;
6991 goto out;
6992 }
6993
6994 /* We have a valid scope declaration, save it */
6995 free(cfg_scope);
6996 cfg_scope = scope;
6997 scope = NULL;
6998
6999 out:
7000 free(scope);
7001 return err_code;
7002}
7003
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004/*
7005 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007006 * Returns the error code, 0 if OK, or any combination of :
7007 * - ERR_ABORT: must abort ASAP
7008 * - ERR_FATAL: we can continue parsing but not start the service
7009 * - ERR_WARN: a warning has been emitted
7010 * - ERR_ALERT: an alert has been emitted
7011 * Only the two first ones can stop processing, the two others are just
7012 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007014int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015{
William Lallemand64e84512015-05-12 14:25:37 +02007016 char *thisline;
7017 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 FILE *f;
7019 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007020 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007021 struct cfg_section *cs = NULL;
7022 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007023 int readbytes = 0;
7024
7025 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007026 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007027 return -1;
7028 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007029
David Carlier97880bb2016-04-08 10:35:26 +01007030 if ((f=fopen(file,"r")) == NULL) {
7031 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034
William Lallemandb2f07452015-05-12 14:27:13 +02007035next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007036 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007037 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007038 char *end;
7039 char *args[MAX_LINE_ARGS + 1];
7040 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007041 int dquote = 0; /* double quote */
7042 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007043
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044 linenum++;
7045
7046 end = line + strlen(line);
7047
William Lallemand64e84512015-05-12 14:25:37 +02007048 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007049 /* Check if we reached the limit and the last char is not \n.
7050 * Watch out for the last line without the terminating '\n'!
7051 */
William Lallemand64e84512015-05-12 14:25:37 +02007052 char *newline;
7053 int newlinesize = linesize * 2;
7054
7055 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7056 if (newline == NULL) {
7057 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7058 file, linenum);
7059 err_code |= ERR_ALERT | ERR_FATAL;
7060 continue;
7061 }
7062
7063 readbytes = linesize - 1;
7064 linesize = newlinesize;
7065 thisline = newline;
7066 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007067 }
7068
William Lallemand64e84512015-05-12 14:25:37 +02007069 readbytes = 0;
7070
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007072 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007073 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007074
Christopher Faulet79bdef32016-11-04 22:36:15 +01007075
7076 if (*line == '[') {/* This is the begining if a scope */
7077 err_code |= cfg_parse_scope(file, linenum, line);
7078 goto next_line;
7079 }
7080
Willy Tarreaubaaee002006-06-26 02:48:02 +02007081 arg = 0;
7082 args[arg] = line;
7083
7084 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007085 if (*line == '"' && !squote) { /* double quote outside single quotes */
7086 if (dquote)
7087 dquote = 0;
7088 else
7089 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007090 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007091 end--;
7092 }
7093 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7094 if (squote)
7095 squote = 0;
7096 else
7097 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007098 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007099 end--;
7100 }
7101 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7103 * C equivalent value. Other combinations left unchanged (eg: \1).
7104 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007105 int skip = 0;
7106 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7107 *line = line[1];
7108 skip = 1;
7109 }
7110 else if (line[1] == 'r') {
7111 *line = '\r';
7112 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 else if (line[1] == 'n') {
7115 *line = '\n';
7116 skip = 1;
7117 }
7118 else if (line[1] == 't') {
7119 *line = '\t';
7120 skip = 1;
7121 }
7122 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007123 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007124 unsigned char hex1, hex2;
7125 hex1 = toupper(line[2]) - '0';
7126 hex2 = toupper(line[3]) - '0';
7127 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7128 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7129 *line = (hex1<<4) + hex2;
7130 skip = 3;
7131 }
7132 else {
7133 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007134 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007135 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007136 } else if (line[1] == '"') {
7137 *line = '"';
7138 skip = 1;
7139 } else if (line[1] == '\'') {
7140 *line = '\'';
7141 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007142 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7143 *line = '$';
7144 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007145 }
7146 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007147 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007148 end -= skip;
7149 }
7150 line++;
7151 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007152 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007153 /* end of string, end of loop */
7154 *line = 0;
7155 break;
7156 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007157 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007158 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007159 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007160 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007161 line++;
7162 args[++arg] = line;
7163 }
William Lallemandb2f07452015-05-12 14:27:13 +02007164 else if (dquote && *line == '$') {
7165 /* environment variables are evaluated inside double quotes */
7166 char *var_beg;
7167 char *var_end;
7168 char save_char;
7169 char *value;
7170 int val_len;
7171 int newlinesize;
7172 int braces = 0;
7173
7174 var_beg = line + 1;
7175 var_end = var_beg;
7176
7177 if (*var_beg == '{') {
7178 var_beg++;
7179 var_end++;
7180 braces = 1;
7181 }
7182
7183 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7184 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7185 err_code |= ERR_ALERT | ERR_FATAL;
7186 goto next_line; /* skip current line */
7187 }
7188
7189 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7190 var_end++;
7191
7192 save_char = *var_end;
7193 *var_end = '\0';
7194 value = getenv(var_beg);
7195 *var_end = save_char;
7196 val_len = value ? strlen(value) : 0;
7197
7198 if (braces) {
7199 if (*var_end == '}') {
7200 var_end++;
7201 braces = 0;
7202 } else {
7203 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7204 err_code |= ERR_ALERT | ERR_FATAL;
7205 goto next_line; /* skip current line */
7206 }
7207 }
7208
7209 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7210
7211 /* if not enough space in thisline */
7212 if (newlinesize > linesize) {
7213 char *newline;
7214
7215 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7216 if (newline == NULL) {
7217 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7218 err_code |= ERR_ALERT | ERR_FATAL;
7219 goto next_line; /* slip current line */
7220 }
7221 /* recompute pointers if realloc returns a new pointer */
7222 if (newline != thisline) {
7223 int i;
7224 int diff;
7225
7226 for (i = 0; i <= arg; i++) {
7227 diff = args[i] - thisline;
7228 args[i] = newline + diff;
7229 }
7230
7231 diff = var_end - thisline;
7232 var_end = newline + diff;
7233 diff = end - thisline;
7234 end = newline + diff;
7235 diff = line - thisline;
7236 line = newline + diff;
7237 thisline = newline;
7238 }
7239 linesize = newlinesize;
7240 }
7241
7242 /* insert value inside the line */
7243 memmove(line + val_len, var_end, end - var_end + 1);
7244 memcpy(line, value, val_len);
7245 end += val_len - (var_end - line);
7246 line += val_len;
7247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007248 else {
7249 line++;
7250 }
7251 }
William Lallemandb2f07452015-05-12 14:27:13 +02007252
William Lallemandf9873ba2015-05-05 17:37:14 +02007253 if (dquote) {
7254 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7255 err_code |= ERR_ALERT | ERR_FATAL;
7256 }
7257
7258 if (squote) {
7259 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7260 err_code |= ERR_ALERT | ERR_FATAL;
7261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007262
7263 /* empty line */
7264 if (!**args)
7265 continue;
7266
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007267 if (*line) {
7268 /* we had to stop due to too many args.
7269 * Let's terminate the string, print the offending part then cut the
7270 * last arg.
7271 */
7272 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7273 line++;
7274 *line = '\0';
7275
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007276 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007277 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007278 err_code |= ERR_ALERT | ERR_FATAL;
7279 args[arg] = line;
7280 }
7281
Willy Tarreau540abe42007-05-02 20:50:16 +02007282 /* zero out remaining args and ensure that at least one entry
7283 * is zeroed out.
7284 */
7285 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007286 args[arg] = line;
7287 }
7288
Willy Tarreau3842f002009-06-14 11:39:52 +02007289 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007290 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007291 char *tmp;
7292
Willy Tarreau3842f002009-06-14 11:39:52 +02007293 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007294 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007295 for (arg=0; *args[arg+1]; arg++)
7296 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007297 *tmp = '\0'; // fix the next arg to \0
7298 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007299 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007300 else if (!strcmp(args[0], "default")) {
7301 kwm = KWM_DEF;
7302 for (arg=0; *args[arg+1]; arg++)
7303 args[arg] = args[arg+1]; // shift args after inversion
7304 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007305
William Lallemand0f99e342011-10-12 17:50:54 +02007306 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7307 strcmp(args[0], "log") != 0) {
7308 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007309 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007310 }
7311
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007312 /* detect section start */
7313 list_for_each_entry(ics, &sections, list) {
7314 if (strcmp(args[0], ics->section_name) == 0) {
7315 cursection = ics->section_name;
7316 cs = ics;
7317 break;
7318 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007319 }
7320
Willy Tarreaubaaee002006-06-26 02:48:02 +02007321 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007322 if (cs)
7323 err_code |= cs->section_parser(file, linenum, args, kwm);
7324 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007325 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007326 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007327 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007328
7329 if (err_code & ERR_ABORT)
7330 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007331 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007332 free(cfg_scope);
7333 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007334 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007335 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007336 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007337 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007338}
7339
Willy Tarreau64ab6072014-09-16 12:17:36 +02007340/* This function propagates processes from frontend <from> to backend <to> so
7341 * that it is always guaranteed that a backend pointed to by a frontend is
7342 * bound to all of its processes. After that, if the target is a "listen"
7343 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007344 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007345 * checked first to ensure that <to> is already bound to all processes of
7346 * <from>, there is no risk of looping and we ensure to follow the shortest
7347 * path to the destination.
7348 *
7349 * It is possible to set <to> to NULL for the first call so that the function
7350 * takes care of visiting the initial frontend in <from>.
7351 *
7352 * It is important to note that the function relies on the fact that all names
7353 * have already been resolved.
7354 */
7355void propagate_processes(struct proxy *from, struct proxy *to)
7356{
7357 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007358
7359 if (to) {
7360 /* check whether we need to go down */
7361 if (from->bind_proc &&
7362 (from->bind_proc & to->bind_proc) == from->bind_proc)
7363 return;
7364
7365 if (!from->bind_proc && !to->bind_proc)
7366 return;
7367
7368 to->bind_proc = from->bind_proc ?
7369 (to->bind_proc | from->bind_proc) : 0;
7370
7371 /* now propagate down */
7372 from = to;
7373 }
7374
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007375 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007376 return;
7377
Willy Tarreauf6b70012014-12-18 14:00:43 +01007378 if (from->state == PR_STSTOPPED)
7379 return;
7380
Willy Tarreau64ab6072014-09-16 12:17:36 +02007381 /* default_backend */
7382 if (from->defbe.be)
7383 propagate_processes(from, from->defbe.be);
7384
7385 /* use_backend */
7386 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007387 if (rule->dynamic)
7388 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007389 to = rule->be.backend;
7390 propagate_processes(from, to);
7391 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007392}
7393
Willy Tarreaubb925012009-07-23 13:36:36 +02007394/*
7395 * Returns the error code, 0 if OK, or any combination of :
7396 * - ERR_ABORT: must abort ASAP
7397 * - ERR_FATAL: we can continue parsing but not start the service
7398 * - ERR_WARN: a warning has been emitted
7399 * - ERR_ALERT: an alert has been emitted
7400 * Only the two first ones can stop processing, the two others are just
7401 * indicators.
7402 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007403int check_config_validity()
7404{
7405 int cfgerr = 0;
7406 struct proxy *curproxy = NULL;
7407 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007408 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007409 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007410 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007411 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007412 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007414 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415 /*
7416 * Now, check for the integrity of all that we have collected.
7417 */
7418
7419 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007420 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007421
Willy Tarreau193b8c62012-11-22 00:17:38 +01007422 if (!global.tune.max_http_hdr)
7423 global.tune.max_http_hdr = MAX_HTTP_HDR;
7424
7425 if (!global.tune.cookie_len)
7426 global.tune.cookie_len = CAPTURE_LEN;
7427
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007428 if (!global.tune.requri_len)
7429 global.tune.requri_len = REQURI_LEN;
7430
Emeric Brun96fd9262017-07-05 13:33:16 +02007431 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7432
Willy Tarreau193b8c62012-11-22 00:17:38 +01007433 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7434
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007435 /* allocate pool of resolution per resolvers */
7436 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7437 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7438 /* error message is already displayed by dns_alloc_resolution_pool() */
7439 err_code |= ERR_ALERT | ERR_ABORT;
7440 goto out;
7441 }
7442 }
7443
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007444 /* Post initialisation of the users and groups lists. */
7445 err_code = userlist_postinit();
7446 if (err_code != ERR_NONE)
7447 goto out;
7448
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007449 /* first, we will invert the proxy list order */
7450 curproxy = NULL;
7451 while (proxy) {
7452 struct proxy *next;
7453
7454 next = proxy->next;
7455 proxy->next = curproxy;
7456 curproxy = proxy;
7457 if (!next)
7458 break;
7459 proxy = next;
7460 }
7461
Willy Tarreau419ead82014-09-16 13:41:21 +02007462 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007463 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007464 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007465 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007466 struct act_rule *trule;
7467 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007468 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007469 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007470 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007471
Willy Tarreau050536d2012-10-04 08:47:34 +02007472 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007473 /* proxy ID not set, use automatic numbering with first
7474 * spare entry starting with next_pxid.
7475 */
7476 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7477 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7478 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007479 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007480 next_pxid++;
7481
Willy Tarreau55ea7572007-06-17 19:56:27 +02007482
Willy Tarreaubaaee002006-06-26 02:48:02 +02007483 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007484 /* ensure we don't keep listeners uselessly bound */
7485 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007486 free((void *)curproxy->table.peers.name);
7487 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007488 continue;
7489 }
7490
Willy Tarreau102df612014-05-07 23:56:38 +02007491 /* Check multi-process mode compatibility for the current proxy */
7492
7493 if (curproxy->bind_proc) {
7494 /* an explicit bind-process was specified, let's check how many
7495 * processes remain.
7496 */
David Carliere6c39412015-07-02 07:00:17 +00007497 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007498
7499 curproxy->bind_proc &= nbits(global.nbproc);
7500 if (!curproxy->bind_proc && nbproc == 1) {
7501 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);
7502 curproxy->bind_proc = 1;
7503 }
7504 else if (!curproxy->bind_proc && nbproc > 1) {
7505 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);
7506 curproxy->bind_proc = 0;
7507 }
7508 }
7509
Willy Tarreau3d209582014-05-09 17:06:11 +02007510 /* check and reduce the bind-proc of each listener */
7511 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7512 unsigned long mask;
7513
7514 if (!bind_conf->bind_proc)
7515 continue;
7516
7517 mask = nbits(global.nbproc);
7518 if (curproxy->bind_proc)
7519 mask &= curproxy->bind_proc;
7520 /* mask cannot be null here thanks to the previous checks */
7521
David Carliere6c39412015-07-02 07:00:17 +00007522 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007523 bind_conf->bind_proc &= mask;
7524
7525 if (!bind_conf->bind_proc && nbproc == 1) {
7526 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",
7527 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7528 bind_conf->bind_proc = mask & ~(mask - 1);
7529 }
7530 else if (!bind_conf->bind_proc && nbproc > 1) {
7531 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",
7532 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7533 bind_conf->bind_proc = 0;
7534 }
7535 }
7536
Willy Tarreauff01a212009-03-15 13:46:16 +01007537 switch (curproxy->mode) {
7538 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007539 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007540 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007541 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007543 cfgerr++;
7544 }
7545
7546 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007547 Warning("config : servers will be ignored for %s '%s'.\n",
7548 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007549 break;
7550
7551 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007552 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007553 break;
7554
7555 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007556 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007557 break;
7558 }
7559
Willy Tarreauf3934b82015-08-11 11:36:45 +02007560 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7561 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7562 proxy_type_str(curproxy), curproxy->id);
7563 err_code |= ERR_WARN;
7564 }
7565
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007566 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007567 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007568 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007569 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007571 cfgerr++;
7572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007573#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007574 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007575 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7576 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007577 cfgerr++;
7578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007579#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007580 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007581 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007583 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007584 }
7585 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007586 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007587 /* If no LB algo is set in a backend, and we're not in
7588 * transparent mode, dispatch mode nor proxy mode, we
7589 * want to use balance roundrobin by default.
7590 */
7591 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7592 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007593 }
7594 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007595
Willy Tarreau1620ec32011-08-06 17:05:02 +02007596 if (curproxy->options & PR_O_DISPATCH)
7597 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7598 else if (curproxy->options & PR_O_HTTP_PROXY)
7599 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7600 else if (curproxy->options & PR_O_TRANSP)
7601 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007602
Willy Tarreau1620ec32011-08-06 17:05:02 +02007603 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7604 if (curproxy->options & PR_O_DISABLE404) {
7605 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7606 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7607 err_code |= ERR_WARN;
7608 curproxy->options &= ~PR_O_DISABLE404;
7609 }
7610 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7611 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7612 "send-state", proxy_type_str(curproxy), curproxy->id);
7613 err_code |= ERR_WARN;
7614 curproxy->options &= ~PR_O2_CHK_SNDST;
7615 }
Willy Tarreauef781042010-01-27 11:53:01 +01007616 }
7617
Simon Horman98637e52014-06-20 12:30:16 +09007618 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7619 if (!global.external_check) {
7620 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7621 curproxy->id, "option external-check");
7622 cfgerr++;
7623 }
7624 if (!curproxy->check_command) {
7625 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7626 curproxy->id, "option external-check");
7627 cfgerr++;
7628 }
7629 }
7630
Simon Horman64e34162015-02-06 11:11:57 +09007631 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007632 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7633 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007634 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7635 "'email-alert myhostname', or 'email-alert to' "
7636 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007637 "to be present).\n",
7638 proxy_type_str(curproxy), curproxy->id);
7639 err_code |= ERR_WARN;
7640 free_email_alert(curproxy);
7641 }
7642 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007643 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007644 }
7645
Simon Horman98637e52014-06-20 12:30:16 +09007646 if (curproxy->check_command) {
7647 int clear = 0;
7648 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7649 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7650 "external-check command", proxy_type_str(curproxy), curproxy->id);
7651 err_code |= ERR_WARN;
7652 clear = 1;
7653 }
7654 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007655 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007656 curproxy->id, "external-check command");
7657 cfgerr++;
7658 }
7659 if (clear) {
7660 free(curproxy->check_command);
7661 curproxy->check_command = NULL;
7662 }
7663 }
7664
7665 if (curproxy->check_path) {
7666 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7667 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7668 "external-check path", proxy_type_str(curproxy), curproxy->id);
7669 err_code |= ERR_WARN;
7670 free(curproxy->check_path);
7671 curproxy->check_path = NULL;
7672 }
7673 }
7674
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007675 /* if a default backend was specified, let's find it */
7676 if (curproxy->defbe.name) {
7677 struct proxy *target;
7678
Willy Tarreauafb39922015-05-26 12:04:09 +02007679 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007680 if (!target) {
7681 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7682 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007683 cfgerr++;
7684 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007685 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7686 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007687 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007688 } else if (target->mode != curproxy->mode &&
7689 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7690
7691 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7692 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7693 curproxy->conf.file, curproxy->conf.line,
7694 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7695 target->conf.file, target->conf.line);
7696 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007697 } else {
7698 free(curproxy->defbe.name);
7699 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007700 /* Update tot_fe_maxconn for a further fullconn's computation */
7701 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007702 /* Emit a warning if this proxy also has some servers */
7703 if (curproxy->srv) {
7704 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7705 curproxy->id);
7706 err_code |= ERR_WARN;
7707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007708 }
7709 }
7710
Emeric Brun3f783572017-01-12 11:21:28 +01007711 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7712 /* Case of listen without default backend
7713 * The curproxy will be its own default backend
7714 * so we update tot_fe_maxconn for a further
7715 * fullconn's computation */
7716 curproxy->tot_fe_maxconn += curproxy->maxconn;
7717 }
7718
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719 /* find the target proxy for 'use_backend' rules */
7720 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007721 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007722 struct logformat_node *node;
7723 char *pxname;
7724
7725 /* Try to parse the string as a log format expression. If the result
7726 * of the parsing is only one entry containing a simple string, then
7727 * it's a standard string corresponding to a static rule, thus the
7728 * parsing is cancelled and be.name is restored to be resolved.
7729 */
7730 pxname = rule->be.name;
7731 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007732 curproxy->conf.args.ctx = ARGC_UBK;
7733 curproxy->conf.args.file = rule->file;
7734 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007735 err = NULL;
7736 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7737 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7738 rule->file, rule->line, pxname, err);
7739 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007740 cfgerr++;
7741 continue;
7742 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007743 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7744
7745 if (!LIST_ISEMPTY(&rule->be.expr)) {
7746 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7747 rule->dynamic = 1;
7748 free(pxname);
7749 continue;
7750 }
7751 /* simple string: free the expression and fall back to static rule */
7752 free(node->arg);
7753 free(node);
7754 }
7755
7756 rule->dynamic = 0;
7757 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007758
Willy Tarreauafb39922015-05-26 12:04:09 +02007759 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007760 if (!target) {
7761 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7762 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007763 cfgerr++;
7764 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007765 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7766 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007767 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007768 } else if (target->mode != curproxy->mode &&
7769 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7770
7771 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7772 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7773 curproxy->conf.file, curproxy->conf.line,
7774 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7775 target->conf.file, target->conf.line);
7776 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007777 } else {
7778 free((void *)rule->be.name);
7779 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007780 /* For each target of switching rules, we update
7781 * their tot_fe_maxconn, except if a previous rule point
7782 * on the same backend or on the default backend */
7783 if (rule->be.backend != curproxy->defbe.be) {
7784 struct switching_rule *swrule;
7785
7786 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7787 if (rule == swrule) {
7788 target->tot_fe_maxconn += curproxy->maxconn;
7789 break;
7790 }
7791 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7792 /* there is multiple ref of this backend */
7793 break;
7794 }
7795 }
7796 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007797 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007798 }
7799
Willy Tarreau64ab6072014-09-16 12:17:36 +02007800 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007801 list_for_each_entry(srule, &curproxy->server_rules, list) {
7802 struct server *target = findserver(curproxy, srule->srv.name);
7803
7804 if (!target) {
7805 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7806 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7807 cfgerr++;
7808 continue;
7809 }
7810 free((void *)srule->srv.name);
7811 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007812 }
7813
Emeric Brunb982a3d2010-01-04 15:45:53 +01007814 /* find the target table for 'stick' rules */
7815 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7816 struct proxy *target;
7817
Emeric Brun1d33b292010-01-04 15:47:17 +01007818 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7819 if (mrule->flags & STK_IS_STORE)
7820 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7821
Emeric Brunb982a3d2010-01-04 15:45:53 +01007822 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007823 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007824 else
7825 target = curproxy;
7826
7827 if (!target) {
7828 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7829 curproxy->id, mrule->table.name);
7830 cfgerr++;
7831 }
7832 else if (target->table.size == 0) {
7833 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7834 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7835 cfgerr++;
7836 }
Willy Tarreau12785782012-04-27 21:37:17 +02007837 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7838 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007839 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7840 cfgerr++;
7841 }
7842 else {
7843 free((void *)mrule->table.name);
7844 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007845 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007846 }
7847 }
7848
7849 /* find the target table for 'store response' rules */
7850 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7851 struct proxy *target;
7852
Emeric Brun1d33b292010-01-04 15:47:17 +01007853 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7854
Emeric Brunb982a3d2010-01-04 15:45:53 +01007855 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007856 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007857 else
7858 target = curproxy;
7859
7860 if (!target) {
7861 Alert("Proxy '%s': unable to find store table '%s'.\n",
7862 curproxy->id, mrule->table.name);
7863 cfgerr++;
7864 }
7865 else if (target->table.size == 0) {
7866 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7867 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7868 cfgerr++;
7869 }
Willy Tarreau12785782012-04-27 21:37:17 +02007870 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7871 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007872 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7873 cfgerr++;
7874 }
7875 else {
7876 free((void *)mrule->table.name);
7877 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007878 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007879 }
7880 }
7881
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007882 /* find the target table for 'tcp-request' layer 4 rules */
7883 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7884 struct proxy *target;
7885
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007886 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007887 continue;
7888
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007889 if (trule->arg.trk_ctr.table.n)
7890 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007891 else
7892 target = curproxy;
7893
7894 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007895 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007896 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007897 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007898 cfgerr++;
7899 }
7900 else if (target->table.size == 0) {
7901 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007902 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007903 cfgerr++;
7904 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007906 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007907 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007908 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007909 cfgerr++;
7910 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007911 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007912 free(trule->arg.trk_ctr.table.n);
7913 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007914 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007915 * to pass a list of counters to track and allocate them right here using
7916 * stktable_alloc_data_type().
7917 */
7918 }
7919 }
7920
Willy Tarreau620408f2016-10-21 16:37:51 +02007921 /* find the target table for 'tcp-request' layer 5 rules */
7922 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7923 struct proxy *target;
7924
7925 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7926 continue;
7927
7928 if (trule->arg.trk_ctr.table.n)
7929 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7930 else
7931 target = curproxy;
7932
7933 if (!target) {
7934 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7935 curproxy->id, trule->arg.trk_ctr.table.n,
7936 tcp_trk_idx(trule->action));
7937 cfgerr++;
7938 }
7939 else if (target->table.size == 0) {
7940 Alert("Proxy '%s': table '%s' used but not configured.\n",
7941 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7942 cfgerr++;
7943 }
7944 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7945 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7946 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7947 tcp_trk_idx(trule->action));
7948 cfgerr++;
7949 }
7950 else {
7951 free(trule->arg.trk_ctr.table.n);
7952 trule->arg.trk_ctr.table.t = &target->table;
7953 /* Note: if we decide to enhance the track-sc syntax, we may be able
7954 * to pass a list of counters to track and allocate them right here using
7955 * stktable_alloc_data_type().
7956 */
7957 }
7958 }
7959
Willy Tarreaud1f96522010-08-03 19:34:32 +02007960 /* find the target table for 'tcp-request' layer 6 rules */
7961 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7962 struct proxy *target;
7963
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007964 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007965 continue;
7966
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007967 if (trule->arg.trk_ctr.table.n)
7968 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007969 else
7970 target = curproxy;
7971
7972 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007973 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007974 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007975 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007976 cfgerr++;
7977 }
7978 else if (target->table.size == 0) {
7979 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007980 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007981 cfgerr++;
7982 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007983 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007984 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007985 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007986 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007987 cfgerr++;
7988 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007989 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007990 free(trule->arg.trk_ctr.table.n);
7991 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007992 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007993 * to pass a list of counters to track and allocate them right here using
7994 * stktable_alloc_data_type().
7995 */
7996 }
7997 }
7998
Baptiste Assmanne9544932015-11-03 23:31:35 +01007999 /* parse http-request capture rules to ensure id really exists */
8000 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8001 if (hrqrule->action != ACT_CUSTOM ||
8002 hrqrule->action_ptr != http_action_req_capture_by_id)
8003 continue;
8004
8005 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8006 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8007 curproxy->id, hrqrule->arg.capid.idx);
8008 cfgerr++;
8009 }
8010 }
8011
8012 /* parse http-response capture rules to ensure id really exists */
8013 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8014 if (hrqrule->action != ACT_CUSTOM ||
8015 hrqrule->action_ptr != http_action_res_capture_by_id)
8016 continue;
8017
8018 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8019 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8020 curproxy->id, hrqrule->arg.capid.idx);
8021 cfgerr++;
8022 }
8023 }
8024
Willy Tarreau09448f72014-06-25 18:12:15 +02008025 /* find the target table for 'http-request' layer 7 rules */
8026 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8027 struct proxy *target;
8028
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008029 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008030 continue;
8031
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008032 if (hrqrule->arg.trk_ctr.table.n)
8033 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008034 else
8035 target = curproxy;
8036
8037 if (!target) {
8038 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008039 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008040 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008041 cfgerr++;
8042 }
8043 else if (target->table.size == 0) {
8044 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008045 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008046 cfgerr++;
8047 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008048 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008049 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008050 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008051 http_trk_idx(hrqrule->action));
8052 cfgerr++;
8053 }
8054 else {
8055 free(hrqrule->arg.trk_ctr.table.n);
8056 hrqrule->arg.trk_ctr.table.t = &target->table;
8057 /* Note: if we decide to enhance the track-sc syntax, we may be able
8058 * to pass a list of counters to track and allocate them right here using
8059 * stktable_alloc_data_type().
8060 */
8061 }
8062 }
8063
8064 /* find the target table for 'http-response' layer 7 rules */
8065 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8066 struct proxy *target;
8067
8068 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8069 continue;
8070
8071 if (hrqrule->arg.trk_ctr.table.n)
8072 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8073 else
8074 target = curproxy;
8075
8076 if (!target) {
8077 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8078 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8079 http_trk_idx(hrqrule->action));
8080 cfgerr++;
8081 }
8082 else if (target->table.size == 0) {
8083 Alert("Proxy '%s': table '%s' used but not configured.\n",
8084 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8085 cfgerr++;
8086 }
8087 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8088 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8089 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8090 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008091 cfgerr++;
8092 }
8093 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008094 free(hrqrule->arg.trk_ctr.table.n);
8095 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008096 /* Note: if we decide to enhance the track-sc syntax, we may be able
8097 * to pass a list of counters to track and allocate them right here using
8098 * stktable_alloc_data_type().
8099 */
8100 }
8101 }
8102
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008103 /* move any "block" rules at the beginning of the http-request rules */
8104 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8105 /* insert block_rules into http_req_rules at the beginning */
8106 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8107 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8108 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8109 curproxy->http_req_rules.n = curproxy->block_rules.n;
8110 LIST_INIT(&curproxy->block_rules);
8111 }
8112
Emeric Brun32da3c42010-09-23 18:39:19 +02008113 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008114 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008115
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008116 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008117 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8118 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008119 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008120 break;
8121 }
8122 }
8123
8124 if (!curpeers) {
8125 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8126 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008127 free((void *)curproxy->table.peers.name);
8128 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008129 cfgerr++;
8130 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008131 else if (curpeers->state == PR_STSTOPPED) {
8132 /* silently disable this peers section */
8133 curproxy->table.peers.p = NULL;
8134 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008135 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008136 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8137 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008138 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008139 cfgerr++;
8140 }
8141 }
8142
Simon Horman9dc49962015-01-30 11:22:59 +09008143
8144 if (curproxy->email_alert.mailers.name) {
8145 struct mailers *curmailers = mailers;
8146
8147 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8148 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8149 free(curproxy->email_alert.mailers.name);
8150 curproxy->email_alert.mailers.m = curmailers;
8151 curmailers->users++;
8152 break;
8153 }
8154 }
8155
8156 if (!curmailers) {
8157 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8158 curproxy->id, curproxy->email_alert.mailers.name);
8159 free_email_alert(curproxy);
8160 cfgerr++;
8161 }
8162 }
8163
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008164 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008165 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008166 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8167 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8168 "proxy", curproxy->id);
8169 cfgerr++;
8170 goto out_uri_auth_compat;
8171 }
8172
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008173 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008174 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008175 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008176 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008177
Willy Tarreau95fa4692010-02-01 13:05:50 +01008178 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8179 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008180
8181 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008182 uri_auth_compat_req[i++] = "realm";
8183 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8184 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008185
Willy Tarreau95fa4692010-02-01 13:05:50 +01008186 uri_auth_compat_req[i++] = "unless";
8187 uri_auth_compat_req[i++] = "{";
8188 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8189 uri_auth_compat_req[i++] = "}";
8190 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008191
Willy Tarreauff011f22011-01-06 17:51:27 +01008192 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8193 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008194 cfgerr++;
8195 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008196 }
8197
Willy Tarreauff011f22011-01-06 17:51:27 +01008198 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008199
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008200 if (curproxy->uri_auth->auth_realm) {
8201 free(curproxy->uri_auth->auth_realm);
8202 curproxy->uri_auth->auth_realm = NULL;
8203 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008204
8205 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008206 }
8207out_uri_auth_compat:
8208
Dragan Dosen43885c72015-10-01 13:18:13 +02008209 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008210 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008211 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8212 if (!curproxy->conf.logformat_sd_string) {
8213 /* set the default logformat_sd_string */
8214 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8215 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008216 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008217 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008218 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008219
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008220 /* compile the log format */
8221 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008222 if (curproxy->conf.logformat_string != default_http_log_format &&
8223 curproxy->conf.logformat_string != default_tcp_log_format &&
8224 curproxy->conf.logformat_string != clf_http_log_format)
8225 free(curproxy->conf.logformat_string);
8226 curproxy->conf.logformat_string = NULL;
8227 free(curproxy->conf.lfs_file);
8228 curproxy->conf.lfs_file = NULL;
8229 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008230
8231 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8232 free(curproxy->conf.logformat_sd_string);
8233 curproxy->conf.logformat_sd_string = NULL;
8234 free(curproxy->conf.lfsd_file);
8235 curproxy->conf.lfsd_file = NULL;
8236 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008237 }
8238
Willy Tarreau62a61232013-04-12 18:13:46 +02008239 if (curproxy->conf.logformat_string) {
8240 curproxy->conf.args.ctx = ARGC_LOG;
8241 curproxy->conf.args.file = curproxy->conf.lfs_file;
8242 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008243 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008244 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008245 SMP_VAL_FE_LOG_END, &err)) {
8246 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8247 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8248 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008249 cfgerr++;
8250 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008251 curproxy->conf.args.file = NULL;
8252 curproxy->conf.args.line = 0;
8253 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008254
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008255 if (curproxy->conf.logformat_sd_string) {
8256 curproxy->conf.args.ctx = ARGC_LOGSD;
8257 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8258 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008259 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008260 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008261 SMP_VAL_FE_LOG_END, &err)) {
8262 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8263 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8264 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008265 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008266 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8267 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8268 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8269 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008270 cfgerr++;
8271 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008272 curproxy->conf.args.file = NULL;
8273 curproxy->conf.args.line = 0;
8274 }
8275
Willy Tarreau62a61232013-04-12 18:13:46 +02008276 if (curproxy->conf.uniqueid_format_string) {
8277 curproxy->conf.args.ctx = ARGC_UIF;
8278 curproxy->conf.args.file = curproxy->conf.uif_file;
8279 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008280 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008281 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 +01008282 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8283 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8284 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8285 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008286 cfgerr++;
8287 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008288 curproxy->conf.args.file = NULL;
8289 curproxy->conf.args.line = 0;
8290 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008291
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008292 /* only now we can check if some args remain unresolved.
8293 * This must be done after the users and groups resolution.
8294 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008295 cfgerr += smp_resolve_args(curproxy);
8296 if (!cfgerr)
8297 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008298
Willy Tarreau2738a142006-07-08 17:28:09 +02008299 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008300 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008301 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008302 (!curproxy->timeout.connect ||
8303 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008304 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008305 " | While not properly invalid, you will certainly encounter various problems\n"
8306 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008307 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008308 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008309 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008310 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008311
Willy Tarreau1fa31262007-12-03 00:36:16 +01008312 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8313 * We must still support older configurations, so let's find out whether those
8314 * parameters have been set or must be copied from contimeouts.
8315 */
8316 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008317 if (!curproxy->timeout.tarpit ||
8318 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008319 /* tarpit timeout not set. We search in the following order:
8320 * default.tarpit, curr.connect, default.connect.
8321 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008322 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008323 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008324 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008325 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008326 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008327 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008328 }
8329 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008330 (!curproxy->timeout.queue ||
8331 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008332 /* queue timeout not set. We search in the following order:
8333 * default.queue, curr.connect, default.connect.
8334 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008335 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008336 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008337 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008338 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008339 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008340 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008341 }
8342 }
8343
Willy Tarreau1620ec32011-08-06 17:05:02 +02008344 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008345 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008346 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008347 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008348 }
8349
Willy Tarreau215663d2014-06-13 18:30:23 +02008350 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8351 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8352 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8353 proxy_type_str(curproxy), curproxy->id);
8354 err_code |= ERR_WARN;
8355 }
8356
Willy Tarreau193b8c62012-11-22 00:17:38 +01008357 /* ensure that cookie capture length is not too large */
8358 if (curproxy->capture_len >= global.tune.cookie_len) {
8359 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8360 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8361 err_code |= ERR_WARN;
8362 curproxy->capture_len = global.tune.cookie_len - 1;
8363 }
8364
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008365 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008366 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008367 curproxy->req_cap_pool = create_pool("ptrcap",
8368 curproxy->nb_req_cap * sizeof(char *),
8369 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008370 }
8371
8372 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008373 curproxy->rsp_cap_pool = create_pool("ptrcap",
8374 curproxy->nb_rsp_cap * sizeof(char *),
8375 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008376 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008377
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008378 switch (curproxy->load_server_state_from_file) {
8379 case PR_SRV_STATE_FILE_UNSPEC:
8380 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8381 break;
8382 case PR_SRV_STATE_FILE_GLOBAL:
8383 if (!global.server_state_file) {
8384 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",
8385 curproxy->id);
8386 err_code |= ERR_WARN;
8387 }
8388 break;
8389 }
8390
Willy Tarreaubaaee002006-06-26 02:48:02 +02008391 /* first, we will invert the servers list order */
8392 newsrv = NULL;
8393 while (curproxy->srv) {
8394 struct server *next;
8395
8396 next = curproxy->srv->next;
8397 curproxy->srv->next = newsrv;
8398 newsrv = curproxy->srv;
8399 if (!next)
8400 break;
8401 curproxy->srv = next;
8402 }
8403
Willy Tarreau17edc812014-01-03 12:14:34 +01008404 /* Check that no server name conflicts. This causes trouble in the stats.
8405 * We only emit a warning for the first conflict affecting each server,
8406 * in order to avoid combinatory explosion if all servers have the same
8407 * name. We do that only for servers which do not have an explicit ID,
8408 * because these IDs were made also for distinguishing them and we don't
8409 * want to annoy people who correctly manage them.
8410 */
8411 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8412 struct server *other_srv;
8413
8414 if (newsrv->puid)
8415 continue;
8416
8417 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8418 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8419 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8420 newsrv->conf.file, newsrv->conf.line,
8421 proxy_type_str(curproxy), curproxy->id,
8422 newsrv->id, other_srv->conf.line);
8423 break;
8424 }
8425 }
8426 }
8427
Willy Tarreaudd701652010-05-25 23:03:02 +02008428 /* assign automatic UIDs to servers which don't have one yet */
8429 next_id = 1;
8430 newsrv = curproxy->srv;
8431 while (newsrv != NULL) {
8432 if (!newsrv->puid) {
8433 /* server ID not set, use automatic numbering with first
8434 * spare entry starting with next_svid.
8435 */
8436 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8437 newsrv->conf.id.key = newsrv->puid = next_id;
8438 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8439 }
8440 next_id++;
8441 newsrv = newsrv->next;
8442 }
8443
Willy Tarreau20697042007-11-15 23:26:18 +01008444 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008445 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008446
Willy Tarreau62c3be22012-01-20 13:12:32 +01008447 /*
8448 * If this server supports a maxconn parameter, it needs a dedicated
8449 * tasks to fill the emptied slots when a connection leaves.
8450 * Also, resolve deferred tracking dependency if needed.
8451 */
8452 newsrv = curproxy->srv;
8453 while (newsrv != NULL) {
8454 if (newsrv->minconn > newsrv->maxconn) {
8455 /* Only 'minconn' was specified, or it was higher than or equal
8456 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8457 * this will avoid further useless expensive computations.
8458 */
8459 newsrv->maxconn = newsrv->minconn;
8460 } else if (newsrv->maxconn && !newsrv->minconn) {
8461 /* minconn was not specified, so we set it to maxconn */
8462 newsrv->minconn = newsrv->maxconn;
8463 }
8464
Willy Tarreau17d45382016-12-22 21:16:08 +01008465 /* this will also properly set the transport layer for prod and checks */
8466 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8467 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8468 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8469 }
Emeric Brun94324a42012-10-11 14:00:19 +02008470
Willy Tarreau2f075e92013-12-03 11:11:34 +01008471 /* set the check type on the server */
8472 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8473
Willy Tarreau62c3be22012-01-20 13:12:32 +01008474 if (newsrv->trackit) {
8475 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008476 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008477 char *pname, *sname;
8478
8479 pname = newsrv->trackit;
8480 sname = strrchr(pname, '/');
8481
8482 if (sname)
8483 *sname++ = '\0';
8484 else {
8485 sname = pname;
8486 pname = NULL;
8487 }
8488
8489 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008490 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008491 if (!px) {
8492 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8493 proxy_type_str(curproxy), curproxy->id,
8494 newsrv->id, pname);
8495 cfgerr++;
8496 goto next_srv;
8497 }
8498 } else
8499 px = curproxy;
8500
8501 srv = findserver(px, sname);
8502 if (!srv) {
8503 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8504 proxy_type_str(curproxy), curproxy->id,
8505 newsrv->id, sname);
8506 cfgerr++;
8507 goto next_srv;
8508 }
8509
Willy Tarreau32091232014-05-16 13:52:00 +02008510 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8511 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8512 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008513 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008514 "tracking as it does not have any check nor agent enabled.\n",
8515 proxy_type_str(curproxy), curproxy->id,
8516 newsrv->id, px->id, srv->id);
8517 cfgerr++;
8518 goto next_srv;
8519 }
8520
8521 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8522
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008523 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008524 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8525 "belongs to a tracking chain looping back to %s/%s.\n",
8526 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008527 newsrv->id, px->id, srv->id, px->id,
8528 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008529 cfgerr++;
8530 goto next_srv;
8531 }
8532
8533 if (curproxy != px &&
8534 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8535 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8536 "tracking: disable-on-404 option inconsistency.\n",
8537 proxy_type_str(curproxy), curproxy->id,
8538 newsrv->id, px->id, srv->id);
8539 cfgerr++;
8540 goto next_srv;
8541 }
8542
Willy Tarreau62c3be22012-01-20 13:12:32 +01008543 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008544 newsrv->tracknext = srv->trackers;
8545 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008546
8547 free(newsrv->trackit);
8548 newsrv->trackit = NULL;
8549 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008550
8551 /*
8552 * resolve server's resolvers name and update the resolvers pointer
8553 * accordingly
8554 */
8555 if (newsrv->resolvers_id) {
8556 struct dns_resolvers *curr_resolvers;
8557 int found;
8558
8559 found = 0;
8560 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8561 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8562 found = 1;
8563 break;
8564 }
8565 }
8566
8567 if (!found) {
8568 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8569 proxy_type_str(curproxy), curproxy->id,
8570 newsrv->id, newsrv->resolvers_id);
8571 cfgerr++;
8572 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008573 if (newsrv->srvrq) {
8574 if (!newsrv->srvrq->resolvers) {
8575 newsrv->srvrq->resolvers = curr_resolvers;
8576 if (dns_link_resolution(newsrv->srvrq,
8577 OBJ_TYPE_SRVRQ, NULL) != 0) {
8578 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8579 proxy_type_str(curproxy), curproxy->id,
8580 newsrv->id);
8581 cfgerr++;
8582 }
8583 }
8584
8585 }
8586 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008587 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008588 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8589 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8590 proxy_type_str(curproxy), curproxy->id,
8591 newsrv->id);
8592 cfgerr++;
8593 }
8594 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008595 }
8596 }
8597 else {
8598 /* if no resolvers section associated to this server
8599 * we can clean up the associated resolution structure
8600 */
8601 if (newsrv->resolution) {
8602 free(newsrv->resolution->hostname_dn);
8603 newsrv->resolution->hostname_dn = NULL;
8604 free(newsrv->resolution);
8605 newsrv->resolution = NULL;
8606 }
8607 }
8608
Willy Tarreau62c3be22012-01-20 13:12:32 +01008609 next_srv:
8610 newsrv = newsrv->next;
8611 }
8612
Olivier Houchard4e694042017-03-14 20:01:29 +01008613 /*
8614 * Try to generate dynamic cookies for servers now.
8615 * It couldn't be done earlier, since at the time we parsed
8616 * the server line, we may not have known yet that we
8617 * should use dynamic cookies, or the secret key may not
8618 * have been provided yet.
8619 */
8620 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8621 newsrv = curproxy->srv;
8622 while (newsrv != NULL) {
8623 srv_set_dyncookie(newsrv);
8624 newsrv = newsrv->next;
8625 }
8626
8627 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008628 /* We have to initialize the server lookup mechanism depending
8629 * on what LB algorithm was choosen.
8630 */
8631
8632 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8633 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8634 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008635 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8636 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8637 init_server_map(curproxy);
8638 } else {
8639 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8640 fwrr_init_server_groups(curproxy);
8641 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008642 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008643
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008644 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008645 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8646 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8647 fwlc_init_server_tree(curproxy);
8648 } else {
8649 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8650 fas_init_server_tree(curproxy);
8651 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008652 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008653
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008654 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008655 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8656 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8657 chash_init_server_tree(curproxy);
8658 } else {
8659 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8660 init_server_map(curproxy);
8661 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008662 break;
8663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008664
8665 if (curproxy->options & PR_O_LOGASAP)
8666 curproxy->to_log &= ~LW_BYTES;
8667
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008668 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008669 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8670 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008671 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8672 proxy_type_str(curproxy), curproxy->id);
8673 err_code |= ERR_WARN;
8674 }
8675
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008676 if (curproxy->mode != PR_MODE_HTTP) {
8677 int optnum;
8678
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008679 if (curproxy->uri_auth) {
8680 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8681 proxy_type_str(curproxy), curproxy->id);
8682 err_code |= ERR_WARN;
8683 curproxy->uri_auth = NULL;
8684 }
8685
Willy Tarreaude7dc882017-03-10 11:49:21 +01008686 if (curproxy->capture_name) {
8687 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8688 proxy_type_str(curproxy), curproxy->id);
8689 err_code |= ERR_WARN;
8690 }
8691
8692 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8693 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8694 proxy_type_str(curproxy), curproxy->id);
8695 err_code |= ERR_WARN;
8696 }
8697
8698 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8699 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8700 proxy_type_str(curproxy), curproxy->id);
8701 err_code |= ERR_WARN;
8702 }
8703
8704 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8705 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8706 proxy_type_str(curproxy), curproxy->id);
8707 err_code |= ERR_WARN;
8708 }
8709
8710 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8711 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8712 proxy_type_str(curproxy), curproxy->id);
8713 err_code |= ERR_WARN;
8714 }
8715
Willy Tarreau87cf5142011-08-19 22:57:24 +02008716 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008717 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8718 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8719 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008720 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008721 }
8722
8723 if (curproxy->options & PR_O_ORGTO) {
8724 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8725 "originalto", proxy_type_str(curproxy), curproxy->id);
8726 err_code |= ERR_WARN;
8727 curproxy->options &= ~PR_O_ORGTO;
8728 }
8729
8730 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8731 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8732 (curproxy->cap & cfg_opts[optnum].cap) &&
8733 (curproxy->options & cfg_opts[optnum].val)) {
8734 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8735 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8736 err_code |= ERR_WARN;
8737 curproxy->options &= ~cfg_opts[optnum].val;
8738 }
8739 }
8740
8741 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8742 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8743 (curproxy->cap & cfg_opts2[optnum].cap) &&
8744 (curproxy->options2 & cfg_opts2[optnum].val)) {
8745 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8746 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8747 err_code |= ERR_WARN;
8748 curproxy->options2 &= ~cfg_opts2[optnum].val;
8749 }
8750 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008751
Willy Tarreau29fbe512015-08-20 19:35:14 +02008752#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008753 if (curproxy->conn_src.bind_hdr_occ) {
8754 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008755 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008756 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008757 err_code |= ERR_WARN;
8758 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008759#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008760 }
8761
Willy Tarreaubaaee002006-06-26 02:48:02 +02008762 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008763 * ensure that we're not cross-dressing a TCP server into HTTP.
8764 */
8765 newsrv = curproxy->srv;
8766 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008767 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008768 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8769 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008770 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008771 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008772
Willy Tarreau0cec3312011-10-31 13:49:26 +01008773 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8774 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8775 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8776 err_code |= ERR_WARN;
8777 }
8778
Willy Tarreauc93cd162014-05-13 15:54:22 +02008779 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008780 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8781 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8782 err_code |= ERR_WARN;
8783 }
8784
Willy Tarreau29fbe512015-08-20 19:35:14 +02008785#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008786 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8787 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008788 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 +01008789 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008790 err_code |= ERR_WARN;
8791 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008792#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008793
8794 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8795 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8796 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8797 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8798 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8799 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",
8800 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8801 err_code |= ERR_WARN;
8802 }
8803
8804
8805 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8806 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",
8807 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8808 err_code |= ERR_WARN;
8809 }
8810 }
8811
Willy Tarreau21d2af32008-02-14 20:25:24 +01008812 newsrv = newsrv->next;
8813 }
8814
Willy Tarreaue42bd962014-09-16 16:21:19 +02008815 /* check if we have a frontend with "tcp-request content" looking at L7
8816 * with no inspect-delay
8817 */
8818 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8819 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008820 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008821 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008822 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008823 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008824 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008825 break;
8826 }
8827
8828 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8829 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8830 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8831 " This means that these rules will randomly find their contents. This can be fixed by"
8832 " setting the tcp-request inspect-delay.\n",
8833 proxy_type_str(curproxy), curproxy->id);
8834 err_code |= ERR_WARN;
8835 }
8836 }
8837
Christopher Fauletd7c91962015-04-30 11:48:27 +02008838 /* Check filter configuration, if any */
8839 cfgerr += flt_check(curproxy);
8840
Willy Tarreauc1a21672009-08-16 22:37:44 +02008841 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008842 if (!curproxy->accept)
8843 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008844
Willy Tarreauc1a21672009-08-16 22:37:44 +02008845 if (curproxy->tcp_req.inspect_delay ||
8846 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008847 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008848
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008849 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008850 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008851 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008852 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008853
8854 /* both TCP and HTTP must check switching rules */
8855 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008856
8857 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008858 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008859 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8860 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 +01008861 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008862 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8863 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008864 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008865 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008866 }
8867
8868 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008869 if (curproxy->tcp_req.inspect_delay ||
8870 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8871 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8872
Emeric Brun97679e72010-09-23 17:56:44 +02008873 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8874 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8875
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008876 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008877 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008878 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008879 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008880
8881 /* If the backend does requires RDP cookie persistence, we have to
8882 * enable the corresponding analyser.
8883 */
8884 if (curproxy->options2 & PR_O2_RDPC_PRST)
8885 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008886
8887 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008888 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008889 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8890 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 +01008891 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008892 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8893 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008894 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008895 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008896 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008897 }
8898
8899 /***********************************************************/
8900 /* At this point, target names have already been resolved. */
8901 /***********************************************************/
8902
8903 /* Check multi-process mode compatibility */
8904
8905 if (global.nbproc > 1 && global.stats_fe) {
8906 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8907 unsigned long mask;
8908
8909 mask = nbits(global.nbproc);
8910 if (global.stats_fe->bind_proc)
8911 mask &= global.stats_fe->bind_proc;
8912
8913 if (bind_conf->bind_proc)
8914 mask &= bind_conf->bind_proc;
8915
8916 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008917 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008918 break;
8919 }
8920 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8921 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");
8922 }
8923 }
8924
8925 /* Make each frontend inherit bind-process from its listeners when not specified. */
8926 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8927 if (curproxy->bind_proc)
8928 continue;
8929
8930 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8931 unsigned long mask;
8932
Willy Tarreaue428b082015-05-04 21:57:58 +02008933 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008934 curproxy->bind_proc |= mask;
8935 }
8936
8937 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008938 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008939 }
8940
8941 if (global.stats_fe) {
8942 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8943 unsigned long mask;
8944
Cyril Bonté06181952016-02-24 00:14:54 +01008945 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008946 global.stats_fe->bind_proc |= mask;
8947 }
8948 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008949 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008950 }
8951
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008952 /* propagate bindings from frontends to backends. Don't do it if there
8953 * are any fatal errors as we must not call it with unresolved proxies.
8954 */
8955 if (!cfgerr) {
8956 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8957 if (curproxy->cap & PR_CAP_FE)
8958 propagate_processes(curproxy, NULL);
8959 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008960 }
8961
8962 /* Bind each unbound backend to all processes when not specified. */
8963 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8964 if (curproxy->bind_proc)
8965 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008966 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008967 }
8968
8969 /*******************************************************/
8970 /* At this step, all proxies have a non-null bind_proc */
8971 /*******************************************************/
8972
8973 /* perform the final checks before creating tasks */
8974
8975 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8976 struct listener *listener;
8977 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008978
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008979 /* Configure SSL for each bind line.
8980 * Note: if configuration fails at some point, the ->ctx member
8981 * remains NULL so that listeners can later detach.
8982 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008983 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008984 if (bind_conf->xprt->prepare_bind_conf &&
8985 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008986 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008987 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008988
Willy Tarreaue6b98942007-10-29 01:09:36 +01008989 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008990 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008991 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008992 int nbproc;
8993
8994 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008995 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008996 nbits(global.nbproc));
8997
8998 if (!nbproc) /* no intersection between listener and frontend */
8999 nbproc = 1;
9000
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009001 if (!listener->luid) {
9002 /* listener ID not set, use automatic numbering with first
9003 * spare entry starting with next_luid.
9004 */
9005 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
9006 listener->conf.id.key = listener->luid = next_id;
9007 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009008 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01009009 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009010
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009011 /* enable separate counters */
9012 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01009013 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009014 if (!listener->name)
9015 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009016 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009017
Willy Tarreaue6b98942007-10-29 01:09:36 +01009018 if (curproxy->options & PR_O_TCP_NOLING)
9019 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009020 if (!listener->maxconn)
9021 listener->maxconn = curproxy->maxconn;
9022 if (!listener->backlog)
9023 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009024 if (!listener->maxaccept)
9025 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9026
9027 /* we want to have an optimal behaviour on single process mode to
9028 * maximize the work at once, but in multi-process we want to keep
9029 * some fairness between processes, so we target half of the max
9030 * number of events to be balanced over all the processes the proxy
9031 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9032 * used to disable the limit.
9033 */
9034 if (listener->maxaccept > 0) {
9035 if (nbproc > 1)
9036 listener->maxaccept = (listener->maxaccept + 1) / 2;
9037 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9038 }
9039
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009040 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009041 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009042 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009043
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009044 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009045 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009046
Willy Tarreau620408f2016-10-21 16:37:51 +02009047 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9048 listener->options |= LI_O_TCP_L5_RULES;
9049
Willy Tarreaude3041d2010-05-31 10:56:17 +02009050 if (curproxy->mon_mask.s_addr)
9051 listener->options |= LI_O_CHK_MONNET;
9052
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009053 /* smart accept mode is automatic in HTTP mode */
9054 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009055 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009056 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9057 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009058 }
9059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009060 /* Release unused SSL configs */
9061 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009062 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9063 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009064 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009065
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009066 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009067 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009068 int count, maxproc = 0;
9069
9070 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009071 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009072 if (count > maxproc)
9073 maxproc = count;
9074 }
9075 /* backends have 0, frontends have 1 or more */
9076 if (maxproc != 1)
9077 Warning("Proxy '%s': in multi-process mode, stats will be"
9078 " limited to process assigned to the current request.\n",
9079 curproxy->id);
9080
Willy Tarreau102df612014-05-07 23:56:38 +02009081 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9082 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9083 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009084 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009085 }
Willy Tarreau102df612014-05-07 23:56:38 +02009086 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9087 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9088 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009089 }
9090 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009091
9092 /* create the task associated with the proxy */
9093 curproxy->task = task_new();
9094 if (curproxy->task) {
9095 curproxy->task->context = curproxy;
9096 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009097 } else {
9098 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9099 curproxy->id);
9100 cfgerr++;
9101 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009102 }
9103
Willy Tarreaufbb78422011-06-05 15:38:35 +02009104 /* automatically compute fullconn if not set. We must not do it in the
9105 * loop above because cross-references are not yet fully resolved.
9106 */
9107 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9108 /* If <fullconn> is not set, let's set it to 10% of the sum of
9109 * the possible incoming frontend's maxconns.
9110 */
9111 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009112 /* we have the sum of the maxconns in <total>. We only
9113 * keep 10% of that sum to set the default fullconn, with
9114 * a hard minimum of 1 (to avoid a divide by zero).
9115 */
Emeric Brun3f783572017-01-12 11:21:28 +01009116 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009117 if (!curproxy->fullconn)
9118 curproxy->fullconn = 1;
9119 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009120 }
9121
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009122 /*
9123 * Recount currently required checks.
9124 */
9125
9126 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9127 int optnum;
9128
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009129 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9130 if (curproxy->options & cfg_opts[optnum].val)
9131 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009132
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009133 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9134 if (curproxy->options2 & cfg_opts2[optnum].val)
9135 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009136 }
9137
Willy Tarreau0fca4832015-05-01 19:12:05 +02009138 /* compute the required process bindings for the peers */
9139 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9140 if (curproxy->table.peers.p)
9141 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9142
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009143 if (cfg_peers) {
9144 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009145 struct peer *p, *pb;
9146
Willy Tarreau1e273012015-05-01 19:15:17 +02009147 /* Remove all peers sections which don't have a valid listener,
9148 * which are not used by any table, or which are bound to more
9149 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009150 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009151 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009152 while (*last) {
9153 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009154
9155 if (curpeers->state == PR_STSTOPPED) {
9156 /* the "disabled" keyword was present */
9157 if (curpeers->peers_fe)
9158 stop_proxy(curpeers->peers_fe);
9159 curpeers->peers_fe = NULL;
9160 }
9161 else if (!curpeers->peers_fe) {
9162 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9163 curpeers->id, localpeer);
9164 }
David Carliere6c39412015-07-02 07:00:17 +00009165 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009166 /* either it's totally stopped or too much used */
9167 if (curpeers->peers_fe->bind_proc) {
9168 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009169 "running in different processes (%d different ones). "
9170 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009171 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009172 cfgerr++;
9173 }
9174 stop_proxy(curpeers->peers_fe);
9175 curpeers->peers_fe = NULL;
9176 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009177 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009178 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009179 last = &curpeers->next;
9180 continue;
9181 }
9182
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009183 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009184 p = curpeers->remote;
9185 while (p) {
9186 pb = p->next;
9187 free(p->id);
9188 free(p);
9189 p = pb;
9190 }
9191
9192 /* Destroy and unlink this curpeers section.
9193 * Note: curpeers is backed up into *last.
9194 */
9195 free(curpeers->id);
9196 curpeers = curpeers->next;
9197 free(*last);
9198 *last = curpeers;
9199 }
9200 }
9201
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009202 /* initialize stick-tables on backend capable proxies. This must not
9203 * be done earlier because the data size may be discovered while parsing
9204 * other proxies.
9205 */
9206 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9207 if (curproxy->state == PR_STSTOPPED)
9208 continue;
9209
9210 if (!stktable_init(&curproxy->table)) {
9211 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9212 cfgerr++;
9213 }
9214 }
9215
Simon Horman0d16a402015-01-30 11:22:58 +09009216 if (mailers) {
9217 struct mailers *curmailers = mailers, **last;
9218 struct mailer *m, *mb;
9219
9220 /* Remove all mailers sections which don't have a valid listener.
9221 * This can happen when a mailers section is never referenced.
9222 */
9223 last = &mailers;
9224 while (*last) {
9225 curmailers = *last;
9226 if (curmailers->users) {
9227 last = &curmailers->next;
9228 continue;
9229 }
9230
9231 Warning("Removing incomplete section 'mailers %s'.\n",
9232 curmailers->id);
9233
9234 m = curmailers->mailer_list;
9235 while (m) {
9236 mb = m->next;
9237 free(m->id);
9238 free(m);
9239 m = mb;
9240 }
9241
9242 /* Destroy and unlink this curmailers section.
9243 * Note: curmailers is backed up into *last.
9244 */
9245 free(curmailers->id);
9246 curmailers = curmailers->next;
9247 free(*last);
9248 *last = curmailers;
9249 }
9250 }
9251
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009252 /* Update server_state_file_name to backend name if backend is supposed to use
9253 * a server-state file locally defined and none has been provided */
9254 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9255 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9256 curproxy->server_state_file_name == NULL)
9257 curproxy->server_state_file_name = strdup(curproxy->id);
9258 }
9259
Willy Tarreau34eb6712011-10-24 18:15:04 +02009260 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009261 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009262 MEM_F_SHARED);
9263
Willy Tarreaubb925012009-07-23 13:36:36 +02009264 if (cfgerr > 0)
9265 err_code |= ERR_ALERT | ERR_FATAL;
9266 out:
9267 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009268}
9269
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009270/*
9271 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9272 * parsing sessions.
9273 */
9274void cfg_register_keywords(struct cfg_kw_list *kwl)
9275{
9276 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9277}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009278
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009279/*
9280 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9281 */
9282void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9283{
9284 LIST_DEL(&kwl->list);
9285 LIST_INIT(&kwl->list);
9286}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009287
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009288/* this function register new section in the haproxy configuration file.
9289 * <section_name> is the name of this new section and <section_parser>
9290 * is the called parser. If two section declaration have the same name,
9291 * only the first declared is used.
9292 */
9293int cfg_register_section(char *section_name,
9294 int (*section_parser)(const char *, int, char **, int))
9295{
9296 struct cfg_section *cs;
9297
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009298 list_for_each_entry(cs, &sections, list) {
9299 if (strcmp(cs->section_name, section_name) == 0) {
9300 Alert("register section '%s': already registered.\n", section_name);
9301 return 0;
9302 }
9303 }
9304
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009305 cs = calloc(1, sizeof(*cs));
9306 if (!cs) {
9307 Alert("register section '%s': out of memory.\n", section_name);
9308 return 0;
9309 }
9310
9311 cs->section_name = section_name;
9312 cs->section_parser = section_parser;
9313
9314 LIST_ADDQ(&sections, &cs->list);
9315
9316 return 1;
9317}
9318
Willy Tarreaubaaee002006-06-26 02:48:02 +02009319/*
David Carlier845efb52015-09-25 11:49:18 +01009320 * free all config section entries
9321 */
9322void cfg_unregister_sections(void)
9323{
9324 struct cfg_section *cs, *ics;
9325
9326 list_for_each_entry_safe(cs, ics, &sections, list) {
9327 LIST_DEL(&cs->list);
9328 free(cs);
9329 }
9330}
9331
Christopher Faulet7110b402016-10-26 11:09:44 +02009332void cfg_backup_sections(struct list *backup_sections)
9333{
9334 struct cfg_section *cs, *ics;
9335
9336 list_for_each_entry_safe(cs, ics, &sections, list) {
9337 LIST_DEL(&cs->list);
9338 LIST_ADDQ(backup_sections, &cs->list);
9339 }
9340}
9341
9342void cfg_restore_sections(struct list *backup_sections)
9343{
9344 struct cfg_section *cs, *ics;
9345
9346 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9347 LIST_DEL(&cs->list);
9348 LIST_ADDQ(&sections, &cs->list);
9349 }
9350}
9351
Willy Tarreau659fbf02016-05-26 17:55:28 +02009352__attribute__((constructor))
9353static void cfgparse_init(void)
9354{
9355 /* Register internal sections */
9356 cfg_register_section("listen", cfg_parse_listen);
9357 cfg_register_section("frontend", cfg_parse_listen);
9358 cfg_register_section("backend", cfg_parse_listen);
9359 cfg_register_section("defaults", cfg_parse_listen);
9360 cfg_register_section("global", cfg_parse_global);
9361 cfg_register_section("userlist", cfg_parse_users);
9362 cfg_register_section("peers", cfg_parse_peers);
9363 cfg_register_section("mailers", cfg_parse_mailers);
9364 cfg_register_section("namespace_list", cfg_parse_netns);
9365 cfg_register_section("resolvers", cfg_parse_resolvers);
9366}
9367
David Carlier845efb52015-09-25 11:49:18 +01009368/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009369 * Local variables:
9370 * c-indent-level: 8
9371 * c-basic-offset: 8
9372 * End:
9373 */