blob: ee249794f967c50b61905f29a64ffd0c5e7da3bb [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
Baptiste Assmann201c07f2017-05-22 15:17:15 +020062#include <proto/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010063#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020064#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020065#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020066#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020067#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010068#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020069#include <proto/lb_fwlc.h>
70#include <proto/lb_fwrr.h>
71#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020074#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020076#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010077#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010078#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020079#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020080#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020081#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020083#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010085#include <proto/task.h>
86#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
88
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100205char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100241 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200243 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (!ss2)
245 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100247 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Emeric Bruned760922010-10-22 17:59:25 +0200258 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
262
263 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200264 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100268 else if (ss2->ss_family == AF_UNSPEC) {
269 socklen_t addr_len;
270
271 /* We want to attach to an already bound fd whose number
272 * is in the addr part of ss2 when cast to sockaddr_in.
273 * Note that by definition there is a single listener.
274 * We still have to determine the address family to
275 * register the correct protocol.
276 */
277 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
278 addr_len = sizeof(*ss2);
279 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
280 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
281 goto fail;
282 }
283
284 port = end = get_host_port(ss2);
285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100287 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200288 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200291 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100292 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200293 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
294 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200298 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100325 * Report an error in <msg> when there are too many arguments. This version is
326 * intended to be used by keyword parsers so that the message will be included
327 * into the general error message. The index is the current keyword in args.
328 * Return 0 if the number of argument is correct, otherwise build a message and
329 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
330 * message may also be null, it will simply not be produced (useful to check only).
331 * <msg> and <err_code> are only affected on error.
332 */
333int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
334{
335 int i;
336
337 if (!*args[index + maxarg + 1])
338 return 0;
339
340 if (msg) {
341 *msg = NULL;
342 memprintf(msg, "%s", args[0]);
343 for (i = 1; i <= index; i++)
344 memprintf(msg, "%s %s", *msg, args[i]);
345
346 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
347 }
348 if (err_code)
349 *err_code |= ERR_ALERT | ERR_FATAL;
350
351 return 1;
352}
353
354/*
355 * same as too_many_args_idx with a 0 index
356 */
357int too_many_args(int maxarg, char **args, char **msg, int *err_code)
358{
359 return too_many_args_idx(maxarg, 0, args, msg, err_code);
360}
361
362/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200363 * Report a fatal Alert when there is too much arguments
364 * The index is the current keyword in args
365 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
366 * Fill err_code with an ERR_ALERT and an ERR_FATAL
367 */
368int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
369{
370 char *kw = NULL;
371 int i;
372
373 if (!*args[index + maxarg + 1])
374 return 0;
375
376 memprintf(&kw, "%s", args[0]);
377 for (i = 1; i <= index; i++) {
378 memprintf(&kw, "%s %s", kw, args[i]);
379 }
380
381 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
382 free(kw);
383 *err_code |= ERR_ALERT | ERR_FATAL;
384 return 1;
385}
386
387/*
388 * same as alertif_too_many_args_idx with a 0 index
389 */
390int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
391{
392 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
393}
394
Willy Tarreau620408f2016-10-21 16:37:51 +0200395/* Report a warning if a rule is placed after a 'tcp-request session' rule.
396 * Return 1 if the warning has been emitted, otherwise 0.
397 */
398int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
399{
400 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
401 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
402 file, line, arg);
403 return 1;
404 }
405 return 0;
406}
407
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200408/* Report a warning if a rule is placed after a 'tcp-request content' rule.
409 * Return 1 if the warning has been emitted, otherwise 0.
410 */
411int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
412{
413 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
414 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
415 file, line, arg);
416 return 1;
417 }
418 return 0;
419}
420
Willy Tarreau61d18892009-03-31 10:49:21 +0200421/* Report a warning if a rule is placed after a 'block' rule.
422 * Return 1 if the warning has been emitted, otherwise 0.
423 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100424int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200425{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200426 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200427 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
428 file, line, arg);
429 return 1;
430 }
431 return 0;
432}
433
Willy Tarreau5002f572014-04-23 01:32:02 +0200434/* Report a warning if a rule is placed after an 'http_request' rule.
435 * Return 1 if the warning has been emitted, otherwise 0.
436 */
437int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
438{
439 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
440 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
441 file, line, arg);
442 return 1;
443 }
444 return 0;
445}
446
Willy Tarreau61d18892009-03-31 10:49:21 +0200447/* Report a warning if a rule is placed after a reqrewrite rule.
448 * Return 1 if the warning has been emitted, otherwise 0.
449 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
452 if (proxy->req_exp) {
453 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
454 file, line, arg);
455 return 1;
456 }
457 return 0;
458}
459
460/* Report a warning if a rule is placed after a reqadd rule.
461 * Return 1 if the warning has been emitted, otherwise 0.
462 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100463int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200464{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100465 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
467 file, line, arg);
468 return 1;
469 }
470 return 0;
471}
472
473/* Report a warning if a rule is placed after a redirect rule.
474 * Return 1 if the warning has been emitted, otherwise 0.
475 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
479 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
480 file, line, arg);
481 return 1;
482 }
483 return 0;
484}
485
486/* Report a warning if a rule is placed after a 'use_backend' rule.
487 * Return 1 if the warning has been emitted, otherwise 0.
488 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100489int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200490{
491 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
492 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
493 file, line, arg);
494 return 1;
495 }
496 return 0;
497}
498
Willy Tarreauee445d92014-04-23 01:39:04 +0200499/* Report a warning if a rule is placed after a 'use-server' rule.
500 * Return 1 if the warning has been emitted, otherwise 0.
501 */
502int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
503{
504 if (!LIST_ISEMPTY(&proxy->server_rules)) {
505 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
506 file, line, arg);
507 return 1;
508 }
509 return 0;
510}
511
Willy Tarreaud39ad442016-11-25 15:16:12 +0100512/* report a warning if a redirect rule is dangerously placed */
513int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200514{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200516 warnif_rule_after_use_server(proxy, file, line, arg);
517}
518
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519/* report a warning if a reqadd rule is dangerously placed */
520int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200521{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522 return warnif_rule_after_redirect(proxy, file, line, arg) ||
523 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200524}
525
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526/* report a warning if a reqxxx rule is dangerously placed */
527int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200528{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100529 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
530 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200531}
532
533/* report a warning if an http-request rule is dangerously placed */
534int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
535{
Willy Tarreau61d18892009-03-31 10:49:21 +0200536 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100537 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200538}
539
Willy Tarreaud39ad442016-11-25 15:16:12 +0100540/* report a warning if a block rule is dangerously placed */
541int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200542{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100543 return warnif_rule_after_http_req(proxy, file, line, arg) ||
544 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200545}
546
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547/* report a warning if a "tcp request content" rule is dangerously placed */
548int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200549{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100550 return warnif_rule_after_block(proxy, file, line, arg) ||
551 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200552}
553
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554/* report a warning if a "tcp request session" rule is dangerously placed */
555int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200556{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100557 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
558 warnif_misplaced_tcp_cont(proxy, file, line, arg);
559}
560
561/* report a warning if a "tcp request connection" rule is dangerously placed */
562int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
563{
564 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
565 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200566}
567
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568/* Report it if a request ACL condition uses some keywords that are incompatible
569 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
570 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
571 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100575 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200576 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100577
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100578 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100579 return 0;
580
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100581 acl = acl_cond_conflicts(cond, where);
582 if (acl) {
583 if (acl->name && *acl->name)
584 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
585 file, line, acl->name, sample_ckp_names(where));
586 else
587 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200588 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 return ERR_WARN;
590 }
591 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100592 return 0;
593
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100594 if (acl->name && *acl->name)
595 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200596 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100597 else
598 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200599 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100600 return ERR_WARN;
601}
602
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 * parse a line in a <global> section. Returns the error code, 0 if OK, or
605 * any combination of :
606 * - ERR_ABORT: must abort ASAP
607 * - ERR_FATAL: we can continue parsing but not start the service
608 * - ERR_WARN: a warning has been emitted
609 * - ERR_ALERT: an alert has been emitted
610 * Only the two first ones can stop processing, the two others are just
611 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200613int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614{
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200616 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617
618 if (!strcmp(args[0], "global")) { /* new section */
619 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200620 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200624 if (alertif_too_many_args(0, file, linenum, args, &err_code))
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 global.mode |= MODE_DAEMON;
627 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200628 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200631 if (*args[1]) {
632 if (!strcmp(args[1], "exit-on-failure")) {
633 global.tune.options |= GTUNE_EXIT_ONFAILURE;
634 } else {
635 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
638 }
639 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200640 global.mode |= MODE_MWORKER;
641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 global.mode |= MODE_DEBUG;
646 }
647 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100660 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100662 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100665 global.tune.options &= ~GTUNE_USE_SPLICE;
666 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200667 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200670 global.tune.options &= ~GTUNE_USE_GAI;
671 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000672 else if (!strcmp(args[0], "noreuseport")) {
673 if (alertif_too_many_args(0, file, linenum, args, &err_code))
674 goto out;
675 global.tune.options &= ~GTUNE_USE_REUSEPORT;
676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200678 if (alertif_too_many_args(0, file, linenum, args, &err_code))
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 global.mode |= MODE_QUIET;
681 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200682 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 if (global.tune.maxpollevents != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200694 }
695 global.tune.maxpollevents = atol(args[1]);
696 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100697 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 if (global.tune.maxaccept != 0) {
701 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 err_code |= ERR_ALERT;
703 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100704 }
705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100709 }
710 global.tune.maxaccept = atol(args[1]);
711 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200712 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.chksize = atol(args[1]);
721 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100722 else if (!strcmp(args[0], "tune.recv_enough")) {
723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.recv_enough = atol(args[1]);
731 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100732 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
734 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740 global.tune.buf_limit = atol(args[1]);
741 if (global.tune.buf_limit) {
742 if (global.tune.buf_limit < 3)
743 global.tune.buf_limit = 3;
744 if (global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
746 }
747 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100748 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200749 if (alertif_too_many_args(1, file, linenum, args, &err_code))
750 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.reserved_bufs = atol(args[1]);
757 if (global.tune.reserved_bufs < 2)
758 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100759 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
760 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100761 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200762 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
764 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200771 if (global.tune.bufsize <= 0) {
772 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100776 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100777 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
779 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
781 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200788 if (global.tune.maxrewrite < 0) {
789 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200793 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100794 else if (!strcmp(args[0], "tune.idletimer")) {
795 unsigned int idle;
796 const char *res;
797
William Lallemand1a748ae2015-05-19 16:37:23 +0200798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
799 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805
806 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
807 if (res) {
808 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
809 file, linenum, *res, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813
814 if (idle > 65535) {
815 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.idle_timer = idle;
820 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100821 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.client_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.client_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.server_rcvbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.server_rcvbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.client_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.client_sndbuf = atol(args[1]);
865 }
866 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100869 if (global.tune.server_sndbuf != 0) {
870 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT;
872 goto out;
873 }
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.server_sndbuf = atol(args[1]);
880 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200881 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.pipesize = atol(args[1]);
890 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100891 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.cookie_len = atol(args[1]) + 1;
900 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200901 else if (!strcmp(args[0], "tune.http.logurilen")) {
902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 global.tune.requri_len = atol(args[1]) + 1;
910 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200911 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200912 if (alertif_too_many_args(1, file, linenum, args, &err_code))
913 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200919 global.tune.max_http_hdr = atoi(args[1]);
920 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
921 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200926 }
William Lallemandf3747832012-11-09 12:33:10 +0100927 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100930 if (*args[1]) {
931 global.tune.comp_maxlevel = atoi(args[1]);
932 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
933 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
934 file, linenum, args[0]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938 } else {
939 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
940 file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200945 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
946 if (*args[1]) {
947 global.tune.pattern_cache = atoi(args[1]);
948 if (global.tune.pattern_cache < 0) {
949 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
950 file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 } else {
955 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
956 file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200962 if (alertif_too_many_args(1, file, linenum, args, &err_code))
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200965 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100974 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
975 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
976 err_code |= ERR_WARN;
977 goto out;
978 }
979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200985 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100994 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
995 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
996 err_code |= ERR_WARN;
997 goto out;
998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
Simon Horman98637e52014-06-20 12:30:16 +09001000 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1002 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001003 global.external_check = 1;
1004 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001005 /* user/group name handling */
1006 else if (!strcmp(args[0], "user")) {
1007 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001008 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1009 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001010 if (global.uid != 0) {
1011 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT;
1013 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001014 }
1015 errno = 0;
1016 ha_user = getpwnam(args[1]);
1017 if (ha_user != NULL) {
1018 global.uid = (int)ha_user->pw_uid;
1019 }
1020 else {
1021 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001023 }
1024 }
1025 else if (!strcmp(args[0], "group")) {
1026 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001027 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1028 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001029 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001030 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT;
1032 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 }
1034 errno = 0;
1035 ha_group = getgrnam(args[1]);
1036 if (ha_group != NULL) {
1037 global.gid = (int)ha_group->gr_gid;
1038 }
1039 else {
1040 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001042 }
1043 }
1044 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001054 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1055 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1056 file, linenum, args[0], LONGBITS, global.nbproc);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.maxconn != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.maxconn = atol(args[1]);
1075#ifdef SYSTEM_MAXCONN
1076 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1077 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1078 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081#endif /* SYSTEM_MAXCONN */
1082 }
Emeric Brun850efd52014-01-29 12:24:34 +01001083 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 if (strcmp(args[1],"none") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1093 else if (strcmp(args[1],"required") == 0)
1094 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1095 else {
1096 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
1099 }
1100 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001101 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1103 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001104 if (global.cps_lim != 0) {
1105 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT;
1107 goto out;
1108 }
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 global.cps_lim = atol(args[1]);
1115 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001116 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001119 if (global.sps_lim != 0) {
1120 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT;
1122 goto out;
1123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
1128 }
1129 global.sps_lim = atol(args[1]);
1130 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001131 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1133 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001134 if (global.ssl_lim != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1136 err_code |= ERR_ALERT;
1137 goto out;
1138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
1143 }
1144 global.ssl_lim = atol(args[1]);
1145 }
William Lallemandd85f9172012-11-09 17:05:39 +01001146 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001147 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1148 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
1153 }
1154 global.comp_rate_lim = atoi(args[1]) * 1024;
1155 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001156 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001159 if (global.maxpipes != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001168 }
1169 global.maxpipes = atol(args[1]);
1170 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001171 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
William Lallemande3a7d992012-11-20 11:25:20 +01001179 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001180 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001181 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001190 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001191 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001198 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (global.rlimit_nofile != 0) {
1201 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 }
1210 global.rlimit_nofile = atol(args[1]);
1211 }
1212 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 if (global.chroot != NULL) {
1216 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001217 err_code |= ERR_ALERT;
1218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 if (*(args[1]) == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 }
1225 global.chroot = strdup(args[1]);
1226 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001227 else if (!strcmp(args[0], "description")) {
1228 int i, len=0;
1229 char *d;
1230
1231 if (!*args[1]) {
1232 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1233 file, linenum, args[0]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
Willy Tarreau348acfe2014-04-14 15:00:39 +02001238 for (i = 1; *args[i]; i++)
1239 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001240
1241 if (global.desc)
1242 free(global.desc);
1243
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001244 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001245
Willy Tarreau348acfe2014-04-14 15:00:39 +02001246 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1247 for (i = 2; *args[i]; i++)
1248 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001249 }
1250 else if (!strcmp(args[0], "node")) {
1251 int i;
1252 char c;
1253
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
1256
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001257 for (i=0; args[1][i]; i++) {
1258 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001259 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1260 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001261 break;
1262 }
1263
1264 if (!i || args[1][i]) {
1265 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1266 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1267 file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if (global.node)
1273 free(global.node);
1274
1275 global.node = strdup(args[1]);
1276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 if (global.pidfile != NULL) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001282 err_code |= ERR_ALERT;
1283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 }
1290 global.pidfile = strdup(args[1]);
1291 }
Emeric Bruned760922010-10-22 17:59:25 +02001292 else if (!strcmp(args[0], "unix-bind")) {
1293 int cur_arg = 1;
1294 while (*(args[cur_arg])) {
1295 if (!strcmp(args[cur_arg], "prefix")) {
1296 if (global.unix_bind.prefix != NULL) {
1297 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1298 err_code |= ERR_ALERT;
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (*(args[cur_arg+1]) == 0) {
1304 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "mode")) {
1314
1315 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1316 cur_arg += 2;
1317 continue;
1318 }
1319
1320 if (!strcmp(args[cur_arg], "uid")) {
1321
1322 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1323 cur_arg += 2;
1324 continue;
1325 }
1326
1327 if (!strcmp(args[cur_arg], "gid")) {
1328
1329 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1330 cur_arg += 2;
1331 continue;
1332 }
1333
1334 if (!strcmp(args[cur_arg], "user")) {
1335 struct passwd *user;
1336
1337 user = getpwnam(args[cur_arg + 1]);
1338 if (!user) {
1339 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1340 file, linenum, args[0], args[cur_arg + 1 ]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 global.unix_bind.ux.uid = user->pw_uid;
1346 cur_arg += 2;
1347 continue;
1348 }
1349
1350 if (!strcmp(args[cur_arg], "group")) {
1351 struct group *group;
1352
1353 group = getgrnam(args[cur_arg + 1]);
1354 if (!group) {
1355 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1356 file, linenum, args[0], args[cur_arg + 1 ]);
1357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
1359 }
1360
1361 global.unix_bind.ux.gid = group->gr_gid;
1362 cur_arg += 2;
1363 continue;
1364 }
1365
Willy Tarreaub48f9582011-09-05 01:17:06 +02001366 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1373 /* delete previous herited or defined syslog servers */
1374 struct logsrv *back;
1375 struct logsrv *tmp;
1376
1377 if (*(args[1]) != 0) {
1378 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
1382
1383 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1384 LIST_DEL(&tmp->list);
1385 free(tmp);
1386 }
1387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001389 struct sockaddr_storage *sk;
1390 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001392 int arg = 0;
1393 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001394
William Lallemand1a748ae2015-05-19 16:37:23 +02001395 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1396 goto out;
1397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 if (*(args[1]) == 0 || *(args[2]) == 0) {
1399 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Vincent Bernat02779b62016-04-03 13:48:43 +02001404 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001405
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 /* just after the address, a length may be specified */
1407 if (strcmp(args[arg+2], "len") == 0) {
1408 len = atoi(args[arg+3]);
1409 if (len < 80 || len > 65535) {
1410 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1411 file, linenum, args[arg+3]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415 logsrv->maxlen = len;
1416
1417 /* skip these two args */
1418 arg += 2;
1419 }
1420 else
1421 logsrv->maxlen = MAX_SYSLOG_LEN;
1422
1423 if (logsrv->maxlen > global.max_syslog_len) {
1424 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001425 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1426 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1427 logline = my_realloc2(logline, global.max_syslog_len + 1);
1428 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001429 }
1430
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 /* after the length, a format may be specified */
1432 if (strcmp(args[arg+2], "format") == 0) {
1433 logsrv->format = get_log_format(args[arg+3]);
1434 if (logsrv->format < 0) {
1435 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1436 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001437 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001438 goto out;
1439 }
1440
1441 /* skip these two args */
1442 arg += 2;
1443 }
1444
David Carlier97880bb2016-04-08 10:35:26 +01001445 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1446 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001447 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001448 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001449
Willy Tarreau18324f52014-06-27 18:10:07 +02001450 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001451 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001452 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001453 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001454 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456
William Lallemand0f99e342011-10-12 17:50:54 +02001457 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001458 if (*(args[arg+3])) {
1459 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001460 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001463 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 }
1466
William Lallemand0f99e342011-10-12 17:50:54 +02001467 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001468 if (*(args[arg+4])) {
1469 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001470 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001471 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001472 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001473 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001474 }
1475 }
1476
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001477 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001478 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001479 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001481 free(logsrv);
1482 goto out;
1483 }
1484 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001485
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001486 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487 if (port1 != port2) {
1488 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1489 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001490 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001491 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001492 goto out;
1493 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001494
William Lallemand0f99e342011-10-12 17:50:54 +02001495 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001496 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001497 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
William Lallemand0f99e342011-10-12 17:50:54 +02001500 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001501 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001502 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1503 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001504
1505 if (global.log_send_hostname != NULL) {
1506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1507 err_code |= ERR_ALERT;
1508 goto out;
1509 }
1510
1511 if (*(args[1]))
1512 name = args[1];
1513 else
1514 name = hostname;
1515
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001516 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001517 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001518 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001519 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1520 if (global.server_state_base != NULL) {
1521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1522 err_code |= ERR_ALERT;
1523 goto out;
1524 }
1525
1526 if (!*(args[1])) {
1527 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1528 err_code |= ERR_FATAL;
1529 goto out;
1530 }
1531
1532 global.server_state_base = strdup(args[1]);
1533 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001534 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1535 if (global.server_state_file != NULL) {
1536 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1537 err_code |= ERR_ALERT;
1538 goto out;
1539 }
1540
1541 if (!*(args[1])) {
1542 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1543 err_code |= ERR_FATAL;
1544 goto out;
1545 }
1546
1547 global.server_state_file = strdup(args[1]);
1548 }
Kevinm48936af2010-12-22 16:08:21 +00001549 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001550 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1551 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001552 if (*(args[1]) == 0) {
1553 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001557 chunk_destroy(&global.log_tag);
1558 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001559 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001561 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1562 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001563 if (global.spread_checks != 0) {
1564 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001565 err_code |= ERR_ALERT;
1566 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001567 }
1568 if (*(args[1]) == 0) {
1569 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001572 }
1573 global.spread_checks = atol(args[1]);
1574 if (global.spread_checks < 0 || global.spread_checks > 50) {
1575 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001579 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1580 const char *err;
1581 unsigned int val;
1582
William Lallemand1a748ae2015-05-19 16:37:23 +02001583 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1584 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001585 if (*(args[1]) == 0) {
1586 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1592 if (err) {
1593 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 }
1596 global.max_spread_checks = val;
1597 if (global.max_spread_checks < 0) {
1598 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 }
1601 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001602 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1603#ifdef USE_CPU_AFFINITY
1604 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001605 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 unsigned long cpus = 0;
1607
1608 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001611 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 proc = atol(args[1]);
1616 if (proc >= 1 && proc <= LONGBITS)
1617 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001618 }
1619
1620 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001621 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1622 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
1627 cur_arg = 2;
1628 while (*args[cur_arg]) {
1629 unsigned int low, high;
1630
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001631 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001632 char *dash = strchr(args[cur_arg], '-');
1633
1634 low = high = str2uic(args[cur_arg]);
1635 if (dash)
1636 high = str2uic(dash + 1);
1637
1638 if (high < low) {
1639 unsigned int swap = low;
1640 low = high;
1641 high = swap;
1642 }
1643
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001644 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001645 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001646 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
1649 }
1650
1651 while (low <= high)
1652 cpus |= 1UL << low++;
1653 }
1654 else {
1655 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1656 file, linenum, args[0], args[cur_arg]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660 cur_arg++;
1661 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001662 for (i = 0; i < LONGBITS; i++)
1663 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001664 global.cpu_map[i] = cpus;
1665#else
1666 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669#endif
1670 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001671 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1672 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1673 goto out;
1674
1675 if (*(args[2]) == 0) {
1676 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680
1681 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1682 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1683 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687 }
1688 else if (!strcmp(args[0], "unsetenv")) {
1689 int arg;
1690
1691 if (*(args[1]) == 0) {
1692 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
1697 for (arg = 1; *args[arg]; arg++) {
1698 if (unsetenv(args[arg]) != 0) {
1699 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703 }
1704 }
1705 else if (!strcmp(args[0], "resetenv")) {
1706 extern char **environ;
1707 char **env = environ;
1708
1709 /* args contain variable names to keep, one per argument */
1710 while (*env) {
1711 int arg;
1712
1713 /* look for current variable in among all those we want to keep */
1714 for (arg = 1; *args[arg]; arg++) {
1715 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1716 (*env)[strlen(args[arg])] == '=')
1717 break;
1718 }
1719
1720 /* delete this variable */
1721 if (!*args[arg]) {
1722 char *delim = strchr(*env, '=');
1723
1724 if (!delim || delim - *env >= trash.size) {
1725 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
1730 memcpy(trash.str, *env, delim - *env);
1731 trash.str[delim - *env] = 0;
1732
1733 if (unsetenv(trash.str) != 0) {
1734 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
1737 }
1738 }
1739 else
1740 env++;
1741 }
1742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001744 struct cfg_kw_list *kwl;
1745 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001746 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001747
1748 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1749 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1750 if (kwl->kw[index].section != CFG_GLOBAL)
1751 continue;
1752 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001753 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001754 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001755 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001758 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001759 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001760 err_code |= ERR_WARN;
1761 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001762 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001764 }
1765 }
1766 }
1767
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001771
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001773 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001774 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775}
1776
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001777void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001779 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 defproxy.mode = PR_MODE_TCP;
1781 defproxy.state = PR_STNEW;
1782 defproxy.maxconn = cfg_maxpconn;
1783 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001784 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001785 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001786
Simon Horman66183002013-02-23 10:16:43 +09001787 defproxy.defsrv.check.inter = DEF_CHKINTR;
1788 defproxy.defsrv.check.fastinter = 0;
1789 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001790 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1791 defproxy.defsrv.agent.fastinter = 0;
1792 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001793 defproxy.defsrv.check.rise = DEF_RISETIME;
1794 defproxy.defsrv.check.fall = DEF_FALLTIME;
1795 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1796 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001797 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001798 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 defproxy.defsrv.maxqueue = 0;
1800 defproxy.defsrv.minconn = 0;
1801 defproxy.defsrv.maxconn = 0;
1802 defproxy.defsrv.slowstart = 0;
1803 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1804 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1805 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001806
1807 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001808 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809}
1810
Willy Tarreauade5ec42010-01-28 19:33:49 +01001811
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1813 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1814 * ERR_FATAL in case of error.
1815 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816static int create_cond_regex_rule(const char *file, int line,
1817 struct proxy *px, int dir, int action, int flags,
1818 const char *cmd, const char *reg, const char *repl,
1819 const char **cond_start)
1820{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001822 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001826 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001827 int cs;
1828 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001829
1830 if (px == &defproxy) {
1831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833 goto err;
1834 }
1835
1836 if (*reg == 0) {
1837 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001838 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001839 goto err;
1840 }
1841
Christopher Faulet898566e2016-10-26 11:06:28 +02001842 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001844
Willy Tarreau5321c422010-01-28 20:35:13 +01001845 if (cond_start &&
1846 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001847 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1848 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1849 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 goto err;
1852 }
1853 }
1854 else if (cond_start && **cond_start) {
1855 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1856 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001858 goto err;
1859 }
1860
Willy Tarreau63af98d2014-05-18 08:11:41 +02001861 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001862 (dir == SMP_OPT_DIR_REQ) ?
1863 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1864 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1865 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868 if (!preg) {
1869 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001870 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871 goto err;
1872 }
1873
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 cs = !(flags & REG_ICASE);
1875 cap = !(flags & REG_NOSUB);
1876 error = NULL;
1877 if (!regex_comp(reg, preg, cs, cap, &error)) {
1878 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1879 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001880 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881 goto err;
1882 }
1883
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001884 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001885 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886 if (repl && err) {
1887 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1888 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001889 ret_code |= ERR_ALERT | ERR_FATAL;
1890 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001891 }
1892
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001893 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code |= ERR_WARN;
1895
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001899 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001900 err:
1901 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001902 free(errmsg);
1903 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904}
1905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906/*
William Lallemand51097192015-04-14 16:35:22 +02001907 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001908 * Returns the error code, 0 if OK, or any combination of :
1909 * - ERR_ABORT: must abort ASAP
1910 * - ERR_FATAL: we can continue parsing but not start the service
1911 * - ERR_WARN: a warning has been emitted
1912 * - ERR_ALERT: an alert has been emitted
1913 * Only the two first ones can stop processing, the two others are just
1914 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001916int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1917{
1918 static struct peers *curpeers = NULL;
1919 struct peer *newpeer = NULL;
1920 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001921 struct bind_conf *bind_conf;
1922 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001923 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001924 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
1926 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001927 if (!*args[1]) {
1928 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001929 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 goto out;
1931 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001932
William Lallemand6e62fb62015-04-28 16:55:23 +02001933 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1934 goto out;
1935
Emeric Brun32da3c42010-09-23 18:39:19 +02001936 err = invalid_char(args[1]);
1937 if (err) {
1938 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1939 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001940 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001941 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 }
1943
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001944 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001945 /*
1946 * If there are two proxies with the same name only following
1947 * combinations are allowed:
1948 */
1949 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001950 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001951 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001953 }
1954 }
1955
Vincent Bernat02779b62016-04-03 13:48:43 +02001956 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1958 err_code |= ERR_ALERT | ERR_ABORT;
1959 goto out;
1960 }
1961
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001962 curpeers->next = cfg_peers;
1963 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001964 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 curpeers->conf.line = linenum;
1966 curpeers->last_change = now.tv_sec;
1967 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001968 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001969 }
1970 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001971 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001972 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001973 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001974
1975 if (!*args[2]) {
1976 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1977 file, linenum, args[0]);
1978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
1980 }
1981
1982 err = invalid_char(args[1]);
1983 if (err) {
1984 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1985 file, linenum, *err, args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
Vincent Bernat02779b62016-04-03 13:48:43 +02001990 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1992 err_code |= ERR_ALERT | ERR_ABORT;
1993 goto out;
1994 }
1995
1996 /* the peers are linked backwards first */
1997 curpeers->count++;
1998 newpeer->next = curpeers->remote;
1999 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002000 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 newpeer->conf.line = linenum;
2002
2003 newpeer->last_change = now.tv_sec;
2004 newpeer->id = strdup(args[1]);
2005
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002006 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002007 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002008 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002011 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002012
2013 proto = protocol_by_family(sk->ss_family);
2014 if (!proto || !proto->connect) {
2015 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2016 file, linenum, args[0], args[1]);
2017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002020
2021 if (port1 != port2) {
2022 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2023 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
2027
Willy Tarreau2aa38802013-02-20 19:20:59 +01002028 if (!port1) {
2029 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2030 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002034
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002037 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002038 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002039
Emeric Brun32da3c42010-09-23 18:39:19 +02002040 if (strcmp(newpeer->id, localpeer) == 0) {
2041 /* Current is local peer, it define a frontend */
2042 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002043 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
2045 if (!curpeers->peers_fe) {
2046 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2048 err_code |= ERR_ALERT | ERR_ABORT;
2049 goto out;
2050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
Willy Tarreau237250c2011-07-29 01:49:03 +02002052 init_new_proxy(curpeers->peers_fe);
2053 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002054 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002055 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2056 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002057 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002059 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060
Willy Tarreau902636f2013-03-10 19:44:48 +01002061 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2062 if (errmsg && *errmsg) {
2063 indent_msg(&errmsg, 2);
2064 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002065 }
2066 else
2067 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2068 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 err_code |= ERR_FATAL;
2070 goto out;
2071 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002072
2073 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002074 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002075 l->maxconn = curpeers->peers_fe->maxconn;
2076 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002077 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002078 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002079 l->analysers |= curpeers->peers_fe->fe_req_ana;
2080 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002081 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2082 global.maxsock += l->maxconn;
2083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002084 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002085 else {
2086 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2087 file, linenum, args[0], args[1],
2088 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2089 err_code |= ERR_FATAL;
2090 goto out;
2091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 }
2093 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002094 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2095 curpeers->state = PR_STSTOPPED;
2096 }
2097 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2098 curpeers->state = PR_STNEW;
2099 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 else if (*args[0] != 0) {
2101 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
2105
2106out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002107 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 return err_code;
2109}
2110
Baptiste Assmann325137d2015-04-13 23:40:55 +02002111/*
2112 * Parse a <resolvers> section.
2113 * Returns the error code, 0 if OK, or any combination of :
2114 * - ERR_ABORT: must abort ASAP
2115 * - ERR_FATAL: we can continue parsing but not start the service
2116 * - ERR_WARN: a warning has been emitted
2117 * - ERR_ALERT: an alert has been emitted
2118 * Only the two first ones can stop processing, the two others are just
2119 * indicators.
2120 */
2121int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2122{
2123 static struct dns_resolvers *curr_resolvers = NULL;
2124 struct dns_nameserver *newnameserver = NULL;
2125 const char *err;
2126 int err_code = 0;
2127 char *errmsg = NULL;
2128
2129 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2132 err_code |= ERR_ALERT | ERR_ABORT;
2133 goto out;
2134 }
2135
2136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2139 file, linenum, *err, args[0], args[1]);
2140 err_code |= ERR_ALERT | ERR_ABORT;
2141 goto out;
2142 }
2143
2144 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2145 /* Error if two resolvers owns the same name */
2146 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2147 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2148 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 }
2151 }
2152
Vincent Bernat02779b62016-04-03 13:48:43 +02002153 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2155 err_code |= ERR_ALERT | ERR_ABORT;
2156 goto out;
2157 }
2158
2159 /* default values */
2160 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2161 curr_resolvers->conf.file = strdup(file);
2162 curr_resolvers->conf.line = linenum;
2163 curr_resolvers->id = strdup(args[1]);
2164 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002165 /* default maximum response size */
2166 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002167 /* default hold period for nx, other, refuse and timeout is 30s */
2168 curr_resolvers->hold.nx = 30000;
2169 curr_resolvers->hold.other = 30000;
2170 curr_resolvers->hold.refused = 30000;
2171 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002172 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002173 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002174 curr_resolvers->hold.valid = 10000;
2175 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002177 /* default resolution pool size */
2178 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002179 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002180 LIST_INIT(&curr_resolvers->resolution.curr);
2181 LIST_INIT(&curr_resolvers->resolution.wait);
2182 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002183 }
2184 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2185 struct sockaddr_storage *sk;
2186 int port1, port2;
2187 struct protocol *proto;
2188
2189 if (!*args[2]) {
2190 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2191 file, linenum, args[0]);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 err = invalid_char(args[1]);
2197 if (err) {
2198 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2199 file, linenum, *err, args[1]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Baptiste Assmanna315c552015-11-02 22:55:49 +01002204 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2205 /* Error if two resolvers owns the same name */
2206 if (strcmp(newnameserver->id, args[1]) == 0) {
2207 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2208 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 }
2211 }
2212
Vincent Bernat02779b62016-04-03 13:48:43 +02002213 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2215 err_code |= ERR_ALERT | ERR_ABORT;
2216 goto out;
2217 }
2218
2219 /* the nameservers are linked backward first */
2220 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2221 curr_resolvers->count_nameservers++;
2222 newnameserver->resolvers = curr_resolvers;
2223 newnameserver->conf.file = strdup(file);
2224 newnameserver->conf.line = linenum;
2225 newnameserver->id = strdup(args[1]);
2226
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002227 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002228 if (!sk) {
2229 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234 proto = protocol_by_family(sk->ss_family);
2235 if (!proto || !proto->connect) {
2236 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2237 file, linenum, args[0], args[1]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
2241
2242 if (port1 != port2) {
2243 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2244 file, linenum, args[0], args[1], args[2]);
2245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
2247 }
2248
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002249 if (!port1 && !port2) {
2250 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2251 file, linenum, args[0], args[1]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 newnameserver->addr = *sk;
2257 }
2258 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2259 const char *res;
2260 unsigned int time;
2261
2262 if (!*args[2]) {
2263 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2264 file, linenum, args[0]);
2265 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2270 if (res) {
2271 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2272 file, linenum, *res, args[0]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002276 if (strcmp(args[1], "nx") == 0)
2277 curr_resolvers->hold.nx = time;
2278 else if (strcmp(args[1], "other") == 0)
2279 curr_resolvers->hold.other = time;
2280 else if (strcmp(args[1], "refused") == 0)
2281 curr_resolvers->hold.refused = time;
2282 else if (strcmp(args[1], "timeout") == 0)
2283 curr_resolvers->hold.timeout = time;
2284 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002285 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002286 else if (strcmp(args[1], "obsolete") == 0)
2287 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002289 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002290 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
2295 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002296 else if (strcmp(args[0], "accepted_payload_size") == 0) {
2297 if (!*args[1]) {
2298 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2299 file, linenum, args[0]);
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303 curr_resolvers->accepted_payload_size = atoi(args[1]);
2304 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002305 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2306 if (!*args[1]) {
2307 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2308 file, linenum, args[0]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312 curr_resolvers->resolution_pool_size = atoi(args[1]);
2313 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002314 else if (strcmp(args[0], "resolve_retries") == 0) {
2315 if (!*args[1]) {
2316 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2317 file, linenum, args[0]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321 curr_resolvers->resolve_retries = atoi(args[1]);
2322 }
2323 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002324 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002325 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2326 file, linenum, args[0]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002330 else if (strcmp(args[1], "retry") == 0) {
2331 const char *res;
2332 unsigned int timeout_retry;
2333
2334 if (!*args[2]) {
2335 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2336 file, linenum, args[0], args[1]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2341 if (res) {
2342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2343 file, linenum, *res, args[0], args[1]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 curr_resolvers->timeout.retry = timeout_retry;
2348 }
2349 else {
2350 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2351 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002355 } /* neither "nameserver" nor "resolvers" */
2356 else if (*args[0] != 0) {
2357 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361
2362 out:
2363 free(errmsg);
2364 return err_code;
2365}
Simon Horman0d16a402015-01-30 11:22:58 +09002366
2367/*
William Lallemand51097192015-04-14 16:35:22 +02002368 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002369 * Returns the error code, 0 if OK, or any combination of :
2370 * - ERR_ABORT: must abort ASAP
2371 * - ERR_FATAL: we can continue parsing but not start the service
2372 * - ERR_WARN: a warning has been emitted
2373 * - ERR_ALERT: an alert has been emitted
2374 * Only the two first ones can stop processing, the two others are just
2375 * indicators.
2376 */
2377int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2378{
2379 static struct mailers *curmailers = NULL;
2380 struct mailer *newmailer = NULL;
2381 const char *err;
2382 int err_code = 0;
2383 char *errmsg = NULL;
2384
2385 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2386 if (!*args[1]) {
2387 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2388 err_code |= ERR_ALERT | ERR_ABORT;
2389 goto out;
2390 }
2391
2392 err = invalid_char(args[1]);
2393 if (err) {
2394 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2395 file, linenum, *err, args[0], args[1]);
2396 err_code |= ERR_ALERT | ERR_ABORT;
2397 goto out;
2398 }
2399
2400 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2401 /*
2402 * If there are two proxies with the same name only following
2403 * combinations are allowed:
2404 */
2405 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002406 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 +09002407 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002409 }
2410 }
2411
Vincent Bernat02779b62016-04-03 13:48:43 +02002412 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002413 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2414 err_code |= ERR_ALERT | ERR_ABORT;
2415 goto out;
2416 }
2417
2418 curmailers->next = mailers;
2419 mailers = curmailers;
2420 curmailers->conf.file = strdup(file);
2421 curmailers->conf.line = linenum;
2422 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002423 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2424 * But need enough time so that timeouts don't occur
2425 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002426 }
2427 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2428 struct sockaddr_storage *sk;
2429 int port1, port2;
2430 struct protocol *proto;
2431
2432 if (!*args[2]) {
2433 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
2439 err = invalid_char(args[1]);
2440 if (err) {
2441 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2442 file, linenum, *err, args[1]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
Vincent Bernat02779b62016-04-03 13:48:43 +02002447 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2449 err_code |= ERR_ALERT | ERR_ABORT;
2450 goto out;
2451 }
2452
2453 /* the mailers are linked backwards first */
2454 curmailers->count++;
2455 newmailer->next = curmailers->mailer_list;
2456 curmailers->mailer_list = newmailer;
2457 newmailer->mailers = curmailers;
2458 newmailer->conf.file = strdup(file);
2459 newmailer->conf.line = linenum;
2460
2461 newmailer->id = strdup(args[1]);
2462
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002463 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002464 if (!sk) {
2465 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
2470 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002471 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2472 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002473 file, linenum, args[0], args[1]);
2474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
2476 }
2477
2478 if (port1 != port2) {
2479 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2480 file, linenum, args[0], args[1], args[2]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484
2485 if (!port1) {
2486 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2487 file, linenum, args[0], args[1], args[2]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492 newmailer->addr = *sk;
2493 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002494 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002495 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002496 }
2497 else if (strcmp(args[0], "timeout") == 0) {
2498 if (!*args[1]) {
2499 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2500 file, linenum, args[0]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504 else if (strcmp(args[1], "mail") == 0) {
2505 const char *res;
2506 unsigned int timeout_mail;
2507 if (!*args[2]) {
2508 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2509 file, linenum, args[0], args[1]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2514 if (res) {
2515 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2516 file, linenum, *res, args[0]);
2517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
2519 }
2520 if (timeout_mail <= 0) {
2521 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 curmailers->timeout.mail = timeout_mail;
2526 } else {
2527 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2528 file, linenum, args[0], args[1]);
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532 }
Simon Horman0d16a402015-01-30 11:22:58 +09002533 else if (*args[0] != 0) {
2534 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
2537 }
2538
2539out:
2540 free(errmsg);
2541 return err_code;
2542}
2543
Simon Horman9dc49962015-01-30 11:22:59 +09002544static void free_email_alert(struct proxy *p)
2545{
2546 free(p->email_alert.mailers.name);
2547 p->email_alert.mailers.name = NULL;
2548 free(p->email_alert.from);
2549 p->email_alert.from = NULL;
2550 free(p->email_alert.to);
2551 p->email_alert.to = NULL;
2552 free(p->email_alert.myhostname);
2553 p->email_alert.myhostname = NULL;
2554}
2555
Willy Tarreau3842f002009-06-14 11:39:52 +02002556int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557{
2558 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002559 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002560 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002561 int rc;
2562 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002563 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002564 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002565 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002566 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002567 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (!strcmp(args[0], "listen"))
2570 rc = PR_CAP_LISTEN;
2571 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002572 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002573 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002574 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002575 else
2576 rc = PR_CAP_NONE;
2577
2578 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 if (!*args[1]) {
2580 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002581 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_ABORT;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002586
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002587 err = invalid_char(args[1]);
2588 if (err) {
2589 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2590 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002592 }
2593
Willy Tarreau8f50b682015-05-26 11:45:02 +02002594 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2595 if (curproxy) {
2596 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2597 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2598 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002600 }
2601
Vincent Bernat02779b62016-04-03 13:48:43 +02002602 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_ABORT;
2605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002607
Willy Tarreau97cb7802010-01-03 20:23:58 +01002608 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 curproxy->next = proxy;
2610 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002611 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2612 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002613 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002616 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617
William Lallemand6e62fb62015-04-28 16:55:23 +02002618 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2619 if (curproxy->cap & PR_CAP_FE)
2620 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623
2624 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002625 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002626 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002627
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002630 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002631 curproxy->no_options = defproxy.no_options;
2632 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002633 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002634 curproxy->except_net = defproxy.except_net;
2635 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002636 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002637 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002639 if (defproxy.fwdfor_hdr_len) {
2640 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2641 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2642 }
2643
Willy Tarreaub86db342009-11-30 11:50:16 +01002644 if (defproxy.orgto_hdr_len) {
2645 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2646 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2647 }
2648
Mark Lamourinec2247f02012-01-04 13:02:01 -05002649 if (defproxy.server_id_hdr_len) {
2650 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2651 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2652 }
2653
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654 if (curproxy->cap & PR_CAP_FE) {
2655 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002656 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002657 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658
2659 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002660 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2661 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002662
2663 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002667 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002668 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 curproxy->fullconn = defproxy.fullconn;
2670 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002671 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002672 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002674 if (defproxy.check_req) {
2675 curproxy->check_req = calloc(1, defproxy.check_len);
2676 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002680 if (defproxy.expect_str) {
2681 curproxy->expect_str = strdup(defproxy.expect_str);
2682 if (defproxy.expect_regex) {
2683 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002684 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2685 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002686 }
2687 }
2688
Willy Tarreau67402132012-05-31 20:40:20 +02002689 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690 if (defproxy.cookie_name)
2691 curproxy->cookie_name = strdup(defproxy.cookie_name);
2692 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002693
2694 if (defproxy.dyncookie_key)
2695 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002696 if (defproxy.cookie_domain)
2697 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002698
Willy Tarreau31936852010-10-06 16:59:56 +02002699 if (defproxy.cookie_maxidle)
2700 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2701
2702 if (defproxy.cookie_maxlife)
2703 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2704
Emeric Brun647caf12009-06-30 17:57:00 +02002705 if (defproxy.rdp_cookie_name)
2706 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2707 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2708
Willy Tarreau01732802007-11-01 22:48:15 +01002709 if (defproxy.url_param_name)
2710 curproxy->url_param_name = strdup(defproxy.url_param_name);
2711 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002712
Benoitaffb4812009-03-25 13:02:10 +01002713 if (defproxy.hh_name)
2714 curproxy->hh_name = strdup(defproxy.hh_name);
2715 curproxy->hh_len = defproxy.hh_len;
2716 curproxy->hh_match_domain = defproxy.hh_match_domain;
2717
Willy Tarreauef9a3602012-12-08 22:29:20 +01002718 if (defproxy.conn_src.iface_name)
2719 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2720 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002721 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002722#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002723 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002724#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002725 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002728 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 if (defproxy.capture_name)
2730 curproxy->capture_name = strdup(defproxy.capture_name);
2731 curproxy->capture_namelen = defproxy.capture_namelen;
2732 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002736 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002737 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002738 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002739 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002740 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 curproxy->mon_net = defproxy.mon_net;
2742 curproxy->mon_mask = defproxy.mon_mask;
2743 if (defproxy.monitor_uri)
2744 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2745 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002746 if (defproxy.defbe.name)
2747 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002748
2749 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002750 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2751 if (curproxy->conf.logformat_string &&
2752 curproxy->conf.logformat_string != default_http_log_format &&
2753 curproxy->conf.logformat_string != default_tcp_log_format &&
2754 curproxy->conf.logformat_string != clf_http_log_format)
2755 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2756
2757 if (defproxy.conf.lfs_file) {
2758 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2759 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2760 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002761
2762 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2763 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2764 if (curproxy->conf.logformat_sd_string &&
2765 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2766 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2767
2768 if (defproxy.conf.lfsd_file) {
2769 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2770 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2771 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002772 }
2773
2774 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002775 curproxy->timeout.connect = defproxy.timeout.connect;
2776 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002777 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002778 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002779 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002780 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002781 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002782 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002783 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002784 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002785 }
2786
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002788 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002789
2790 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002791 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002792 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002793 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002794 LIST_INIT(&node->list);
2795 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2796 }
2797
Willy Tarreau62a61232013-04-12 18:13:46 +02002798 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2799 if (curproxy->conf.uniqueid_format_string)
2800 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2801
Dragan Dosen43885c72015-10-01 13:18:13 +02002802 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002803
Willy Tarreau62a61232013-04-12 18:13:46 +02002804 if (defproxy.conf.uif_file) {
2805 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2806 curproxy->conf.uif_line = defproxy.conf.uif_line;
2807 }
William Lallemanda73203e2012-03-12 12:48:57 +01002808
2809 /* copy default header unique id */
2810 if (defproxy.header_unique_id)
2811 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2812
William Lallemand82fe75c2012-10-23 10:25:10 +02002813 /* default compression options */
2814 if (defproxy.comp != NULL) {
2815 curproxy->comp = calloc(1, sizeof(struct comp));
2816 curproxy->comp->algos = defproxy.comp->algos;
2817 curproxy->comp->types = defproxy.comp->types;
2818 }
2819
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002821 curproxy->conf.used_listener_id = EB_ROOT;
2822 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002823
Simon Horman98637e52014-06-20 12:30:16 +09002824 if (defproxy.check_path)
2825 curproxy->check_path = strdup(defproxy.check_path);
2826 if (defproxy.check_command)
2827 curproxy->check_command = strdup(defproxy.check_command);
2828
Simon Horman9dc49962015-01-30 11:22:59 +09002829 if (defproxy.email_alert.mailers.name)
2830 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2831 if (defproxy.email_alert.from)
2832 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2833 if (defproxy.email_alert.to)
2834 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2835 if (defproxy.email_alert.myhostname)
2836 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002837 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002838 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002839
Willy Tarreau93893792009-07-23 13:19:11 +02002840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2843 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002844 /* FIXME-20070101: we should do this too at the end of the
2845 * config parsing to free all default values.
2846 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002847 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2848 err_code |= ERR_ABORT;
2849 goto out;
2850 }
2851
Willy Tarreaua534fea2008-08-03 12:19:50 +02002852 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002853 free(defproxy.check_command);
2854 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002855 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002856 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002857 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002858 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002859 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002860 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002861 free(defproxy.capture_name);
2862 free(defproxy.monitor_uri);
2863 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002864 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002865 free(defproxy.fwdfor_hdr_name);
2866 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002867 free(defproxy.orgto_hdr_name);
2868 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002869 free(defproxy.server_id_hdr_name);
2870 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002871 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002872 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002873 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002874 free(defproxy.expect_regex);
2875 defproxy.expect_regex = NULL;
2876 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002877
Willy Tarreau62a61232013-04-12 18:13:46 +02002878 if (defproxy.conf.logformat_string != default_http_log_format &&
2879 defproxy.conf.logformat_string != default_tcp_log_format &&
2880 defproxy.conf.logformat_string != clf_http_log_format)
2881 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002882
Willy Tarreau62a61232013-04-12 18:13:46 +02002883 free(defproxy.conf.uniqueid_format_string);
2884 free(defproxy.conf.lfs_file);
2885 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002886 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002887 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002888
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002889 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2890 free(defproxy.conf.logformat_sd_string);
2891 free(defproxy.conf.lfsd_file);
2892
Willy Tarreaua534fea2008-08-03 12:19:50 +02002893 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002894 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002895
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 /* we cannot free uri_auth because it might already be used */
2897 init_default_instance();
2898 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002899 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2900 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 }
2904 else if (curproxy == NULL) {
2905 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002909
2910 /* update the current file and line being parsed */
2911 curproxy->conf.args.file = curproxy->conf.file;
2912 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913
2914 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002915 if (!strcmp(args[0], "server") ||
2916 !strcmp(args[0], "default-server") ||
2917 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002918 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2919 if (err_code & ERR_FATAL)
2920 goto out;
2921 }
2922 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002923 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002924 int cur_arg;
2925
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (curproxy == &defproxy) {
2927 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002931 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933
Willy Tarreau24709282013-03-10 21:32:12 +01002934 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002935 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002940
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002941 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002942
2943 /* use default settings for unix sockets */
2944 bind_conf->ux.uid = global.unix_bind.ux.uid;
2945 bind_conf->ux.gid = global.unix_bind.ux.gid;
2946 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002947
2948 /* NOTE: the following line might create several listeners if there
2949 * are comma-separated IPs or port ranges. So all further processing
2950 * will have to be applied to all listeners created after last_listen.
2951 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002952 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2953 if (errmsg && *errmsg) {
2954 indent_msg(&errmsg, 2);
2955 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002956 }
2957 else
2958 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2959 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002963
Willy Tarreau4348fad2012-09-20 16:48:07 +02002964 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2965 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002966 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002967 }
2968
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002969 cur_arg = 2;
2970 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002971 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002972 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002973 char *err;
2974
Willy Tarreau26982662012-09-12 23:17:10 +02002975 kw = bind_find_kw(args[cur_arg]);
2976 if (kw) {
2977 char *err = NULL;
2978 int code;
2979
2980 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002981 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2982 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002983 cur_arg += 1 + kw->skip ;
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
Willy Tarreau4348fad2012-09-20 16:48:07 +02002988 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002989 err_code |= code;
2990
2991 if (code) {
2992 if (err && *err) {
2993 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002994 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002995 }
2996 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002997 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2998 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002999 if (code & ERR_FATAL) {
3000 free(err);
3001 cur_arg += 1 + kw->skip;
3002 goto out;
3003 }
3004 }
3005 free(err);
3006 cur_arg += 1 + kw->skip;
3007 continue;
3008 }
3009
Willy Tarreau8638f482012-09-18 18:01:17 +02003010 err = NULL;
3011 if (!bind_dumped) {
3012 bind_dump_kws(&err);
3013 indent_msg(&err, 4);
3014 bind_dumped = 1;
3015 }
3016
3017 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3018 file, linenum, args[0], args[1], args[cur_arg],
3019 err ? " Registered keywords :" : "", err ? err : "");
3020 free(err);
3021
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003024 }
Willy Tarreau93893792009-07-23 13:19:11 +02003025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 }
3027 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003028 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003034 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003036
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 /* flush useless bits */
3038 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003041 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003042 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003044
William Lallemanddf1425a2015-04-28 20:17:49 +02003045 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3046 goto out;
3047
Willy Tarreau1c47f852006-07-09 08:22:27 +02003048 if (!*args[1]) {
3049 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003053 }
3054
Willy Tarreaua534fea2008-08-03 12:19:50 +02003055 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003056 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003057 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003058 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003059 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3060
Willy Tarreau93893792009-07-23 13:19:11 +02003061 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003064 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3065 goto out;
3066
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3068 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3069 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3070 else {
3071 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003076 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003077 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003078
3079 if (curproxy == &defproxy) {
3080 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003084 }
3085
William Lallemanddf1425a2015-04-28 20:17:49 +02003086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3087 goto out;
3088
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003089 if (!*args[1]) {
3090 Alert("parsing [%s:%d]: '%s' expects an integer argument.\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
3096 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003097 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003098 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003099
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003100 if (curproxy->uuid <= 0) {
3101 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003102 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003105 }
3106
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003107 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3108 if (node) {
3109 struct proxy *target = container_of(node, struct proxy, conf.id);
3110 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3111 file, linenum, proxy_type_str(curproxy), curproxy->id,
3112 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003117 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003118 else if (!strcmp(args[0], "description")) {
3119 int i, len=0;
3120 char *d;
3121
Cyril Bonté99ed3272010-01-24 23:29:44 +01003122 if (curproxy == &defproxy) {
3123 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3124 file, linenum, args[0]);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003129 if (!*args[1]) {
3130 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3131 file, linenum, args[0]);
3132 return -1;
3133 }
3134
Willy Tarreau348acfe2014-04-14 15:00:39 +02003135 for (i = 1; *args[i]; i++)
3136 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003137
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003138 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003139 curproxy->desc = d;
3140
Willy Tarreau348acfe2014-04-14 15:00:39 +02003141 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3142 for (i = 2; *args[i]; i++)
3143 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003144
3145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003147 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 curproxy->state = PR_STSTOPPED;
3150 }
3151 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003152 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 curproxy->state = PR_STNEW;
3155 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003156 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3157 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003158 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003159
3160 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003161 unsigned int low, high;
3162
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003163 if (strcmp(args[cur_arg], "all") == 0) {
3164 set = 0;
3165 break;
3166 }
3167 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003168 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003169 }
3170 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003171 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003172 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003173 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003174 char *dash = strchr(args[cur_arg], '-');
3175
3176 low = high = str2uic(args[cur_arg]);
3177 if (dash)
3178 high = str2uic(dash + 1);
3179
3180 if (high < low) {
3181 unsigned int swap = low;
3182 low = high;
3183 high = swap;
3184 }
3185
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003186 if (low < 1 || high > LONGBITS) {
3187 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3188 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003191 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003192 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003193 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003194 }
3195 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003196 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3197 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003200 }
3201 cur_arg++;
3202 }
3203 curproxy->bind_proc = set;
3204 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003205 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003206 if (curproxy == &defproxy) {
3207 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003210 }
3211
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003212 err = invalid_char(args[1]);
3213 if (err) {
3214 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3215 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003217 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003218 }
3219
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003220 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003221 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3222 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003225 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003226 }
3227 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3228
3229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3230 err_code |= ERR_WARN;
3231
3232 if (*(args[1]) == 0) {
3233 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3234 file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238 free(curproxy->dyncookie_key);
3239 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3242 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243
Willy Tarreau977b8e42006-12-29 14:19:17 +01003244 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003246
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 if (*(args[1]) == 0) {
3248 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3249 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003253
Willy Tarreau67402132012-05-31 20:40:20 +02003254 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003255 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003256 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003257 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 curproxy->cookie_name = strdup(args[1]);
3259 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003260
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 cur_arg = 2;
3262 while (*(args[cur_arg])) {
3263 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003264 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 }
3266 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003267 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 }
3269 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003270 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
3272 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003273 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 }
3275 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003276 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003278 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003279 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003282 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003284 else if (!strcmp(args[cur_arg], "httponly")) {
3285 curproxy->ck_opts |= PR_CK_HTTPONLY;
3286 }
3287 else if (!strcmp(args[cur_arg], "secure")) {
3288 curproxy->ck_opts |= PR_CK_SECURE;
3289 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003290 else if (!strcmp(args[cur_arg], "domain")) {
3291 if (!*args[cur_arg + 1]) {
3292 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3293 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003296 }
3297
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003298 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003299 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003300 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3301 " dots nor does not start with a dot."
3302 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003303 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003304 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003305 }
3306
3307 err = invalid_domainchar(args[cur_arg + 1]);
3308 if (err) {
3309 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3310 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003313 }
3314
Willy Tarreau68a897b2009-12-03 23:28:34 +01003315 if (!curproxy->cookie_domain) {
3316 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3317 } else {
3318 /* one domain was already specified, add another one by
3319 * building the string which will be returned along with
3320 * the cookie.
3321 */
3322 char *new_ptr;
3323 int new_len = strlen(curproxy->cookie_domain) +
3324 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3325 new_ptr = malloc(new_len);
3326 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3327 free(curproxy->cookie_domain);
3328 curproxy->cookie_domain = new_ptr;
3329 }
Willy Tarreau31936852010-10-06 16:59:56 +02003330 cur_arg++;
3331 }
3332 else if (!strcmp(args[cur_arg], "maxidle")) {
3333 unsigned int maxidle;
3334 const char *res;
3335
3336 if (!*args[cur_arg + 1]) {
3337 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3338 file, linenum, args[cur_arg]);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342
3343 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3344 if (res) {
3345 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3346 file, linenum, *res, args[cur_arg]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350 curproxy->cookie_maxidle = maxidle;
3351 cur_arg++;
3352 }
3353 else if (!strcmp(args[cur_arg], "maxlife")) {
3354 unsigned int maxlife;
3355 const char *res;
3356
3357 if (!*args[cur_arg + 1]) {
3358 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3359 file, linenum, args[cur_arg]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
3364 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3365 if (res) {
3366 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3367 file, linenum, *res, args[cur_arg]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003372 cur_arg++;
3373 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003374 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003375
3376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3377 err_code |= ERR_WARN;
3378 curproxy->ck_opts |= PR_CK_DYNAMIC;
3379 }
3380
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003382 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 +02003383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387 cur_arg++;
3388 }
Willy Tarreau67402132012-05-31 20:40:20 +02003389 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3391 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394
Willy Tarreau67402132012-05-31 20:40:20 +02003395 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3397 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003400
Willy Tarreau67402132012-05-31 20:40:20 +02003401 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003402 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3403 file, linenum);
3404 err_code |= ERR_ALERT | ERR_FATAL;
3405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003407 else if (!strcmp(args[0], "email-alert")) {
3408 if (*(args[1]) == 0) {
3409 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3410 file, linenum, args[0]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
3415 if (!strcmp(args[1], "from")) {
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 free(curproxy->email_alert.from);
3423 curproxy->email_alert.from = strdup(args[2]);
3424 }
3425 else if (!strcmp(args[1], "mailers")) {
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.mailers.name);
3433 curproxy->email_alert.mailers.name = strdup(args[2]);
3434 }
3435 else if (!strcmp(args[1], "myhostname")) {
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.myhostname);
3443 curproxy->email_alert.myhostname = strdup(args[2]);
3444 }
Simon Horman64e34162015-02-06 11:11:57 +09003445 else if (!strcmp(args[1], "level")) {
3446 curproxy->email_alert.level = get_log_level(args[2]);
3447 if (curproxy->email_alert.level < 0) {
3448 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3449 file, linenum, args[1], args[2]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 }
Simon Horman9dc49962015-01-30 11:22:59 +09003454 else if (!strcmp(args[1], "to")) {
3455 if (*(args[1]) == 0) {
3456 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3457 file, linenum, args[1]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461 free(curproxy->email_alert.to);
3462 curproxy->email_alert.to = strdup(args[2]);
3463 }
3464 else {
3465 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3466 file, linenum, args[1]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
Simon Horman64e34162015-02-06 11:11:57 +09003470 /* Indicate that the email_alert is at least partially configured */
3471 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003472 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003473 else if (!strcmp(args[0], "external-check")) {
3474 if (*(args[1]) == 0) {
3475 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3476 file, linenum, args[0]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480
3481 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003482 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003483 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003484 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003485 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3486 file, linenum, args[1]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490 free(curproxy->check_command);
3491 curproxy->check_command = strdup(args[2]);
3492 }
3493 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003494 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003495 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003496 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003497 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3498 file, linenum, args[1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 free(curproxy->check_path);
3503 curproxy->check_path = strdup(args[2]);
3504 }
3505 else {
3506 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3507 file, linenum, args[1]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003512 else if (!strcmp(args[0], "persist")) { /* persist */
3513 if (*(args[1]) == 0) {
3514 Alert("parsing [%s:%d] : missing persist method.\n",
3515 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003518 }
3519
3520 if (!strncmp(args[1], "rdp-cookie", 10)) {
3521 curproxy->options2 |= PR_O2_RDPC_PRST;
3522
Emeric Brunb982a3d2010-01-04 15:45:53 +01003523 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003524 const char *beg, *end;
3525
3526 beg = args[1] + 11;
3527 end = strchr(beg, ')');
3528
William Lallemanddf1425a2015-04-28 20:17:49 +02003529 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3530 goto out;
3531
Emeric Brun647caf12009-06-30 17:57:00 +02003532 if (!end || end == beg) {
3533 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003537 }
3538
3539 free(curproxy->rdp_cookie_name);
3540 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3541 curproxy->rdp_cookie_len = end-beg;
3542 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003543 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003544 free(curproxy->rdp_cookie_name);
3545 curproxy->rdp_cookie_name = strdup("msts");
3546 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3547 }
3548 else { /* syntax */
3549 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003553 }
3554 }
3555 else {
3556 Alert("parsing [%s:%d] : unknown persist method.\n",
3557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003560 }
3561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003563 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
3566 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003567 else if (!strcmp(args[0], "load-server-state-from-file")) {
3568 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3569 err_code |= ERR_WARN;
3570 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3571 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3572 }
3573 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3574 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3575 }
3576 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3577 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3578 }
3579 else {
3580 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3581 file, linenum, args[0], args[1]);
3582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
3584 }
3585 }
3586 else if (!strcmp(args[0], "server-state-file-name")) {
3587 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3588 err_code |= ERR_WARN;
3589 if (*(args[1]) == 0) {
3590 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3591 file, linenum, args[0]);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594 }
3595 else if (!strcmp(args[1], "use-backend-name"))
3596 curproxy->server_state_file_name = strdup(curproxy->id);
3597 else
3598 curproxy->server_state_file_name = strdup(args[1]);
3599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003603
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003605 if (curproxy == &defproxy) {
3606 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
3609 }
3610
William Lallemand1a748ae2015-05-19 16:37:23 +02003611 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3612 goto out;
3613
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 if (*(args[4]) == 0) {
3615 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003620 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 curproxy->capture_name = strdup(args[2]);
3622 curproxy->capture_namelen = strlen(curproxy->capture_name);
3623 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 curproxy->to_log |= LW_COOKIE;
3625 }
3626 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3627 struct cap_hdr *hdr;
3628
3629 if (curproxy == &defproxy) {
3630 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 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634
William Lallemand1a748ae2015-05-19 16:37:23 +02003635 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3636 goto out;
3637
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3639 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3640 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
Vincent Bernat02779b62016-04-03 13:48:43 +02003645 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 hdr->next = curproxy->req_cap;
3647 hdr->name = strdup(args[3]);
3648 hdr->namelen = strlen(args[3]);
3649 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003650 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 hdr->index = curproxy->nb_req_cap++;
3652 curproxy->req_cap = hdr;
3653 curproxy->to_log |= LW_REQHDR;
3654 }
3655 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3656 struct cap_hdr *hdr;
3657
3658 if (curproxy == &defproxy) {
3659 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 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
3663
William Lallemand1a748ae2015-05-19 16:37:23 +02003664 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3665 goto out;
3666
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3668 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3669 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 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003673 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 hdr->next = curproxy->rsp_cap;
3675 hdr->name = strdup(args[3]);
3676 hdr->namelen = strlen(args[3]);
3677 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003678 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 hdr->index = curproxy->nb_rsp_cap++;
3680 curproxy->rsp_cap = hdr;
3681 curproxy->to_log |= LW_RSPHDR;
3682 }
3683 else {
3684 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
3689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003693
William Lallemanddf1425a2015-04-28 20:17:49 +02003694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3695 goto out;
3696
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 if (*(args[1]) == 0) {
3698 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
3703 curproxy->conn_retries = atol(args[1]);
3704 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003705 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003706 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003707
3708 if (curproxy == &defproxy) {
3709 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
3713
Willy Tarreau20b0de52012-12-24 15:45:22 +01003714 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003715 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003716 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3717 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3718 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3719 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003720 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 +01003721 file, linenum, args[0]);
3722 err_code |= ERR_WARN;
3723 }
3724
Willy Tarreauff011f22011-01-06 17:51:27 +01003725 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003726
Willy Tarreauff011f22011-01-06 17:51:27 +01003727 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003728 err_code |= ERR_ALERT | ERR_ABORT;
3729 goto out;
3730 }
3731
Willy Tarreau5002f572014-04-23 01:32:02 +02003732 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003733 err_code |= warnif_cond_conflicts(rule->cond,
3734 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3735 file, linenum);
3736
Willy Tarreauff011f22011-01-06 17:51:27 +01003737 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003738 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003739 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003740 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003741
3742 if (curproxy == &defproxy) {
3743 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
3746 }
3747
3748 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003749 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003750 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3751 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003752 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3753 file, linenum, args[0]);
3754 err_code |= ERR_WARN;
3755 }
3756
3757 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3758
3759 if (!rule) {
3760 err_code |= ERR_ALERT | ERR_ABORT;
3761 goto out;
3762 }
3763
3764 err_code |= warnif_cond_conflicts(rule->cond,
3765 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3766 file, linenum);
3767
3768 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3769 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003770 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3771 /* set the header name and length into the proxy structure */
3772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3773 err_code |= ERR_WARN;
3774
3775 if (!*args[1]) {
3776 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3777 file, linenum, args[0]);
3778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
3780 }
3781
3782 /* set the desired header name */
3783 free(curproxy->server_id_hdr_name);
3784 curproxy->server_id_hdr_name = strdup(args[1]);
3785 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3786 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003787 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003788 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003789
Willy Tarreaub099aca2008-10-12 17:26:37 +02003790 if (curproxy == &defproxy) {
3791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003794 }
3795
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003796 /* emulate "block" using "http-request block". Since these rules are supposed to
3797 * be processed before all http-request rules, we put them into their own list
3798 * and will insert them at the end.
3799 */
3800 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3801 if (!rule) {
3802 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003803 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003804 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003805 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3806 err_code |= warnif_cond_conflicts(rule->cond,
3807 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3808 file, linenum);
3809 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003810
3811 if (!already_warned(WARN_BLOCK_DEPRECATED))
3812 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]);
3813
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003814 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003815 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003816 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003817
Cyril Bonté99ed3272010-01-24 23:29:44 +01003818 if (curproxy == &defproxy) {
3819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823
Willy Tarreaube4653b2015-05-28 15:26:58 +02003824 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003825 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3826 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003829 }
3830
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003831 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003832 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003833 err_code |= warnif_cond_conflicts(rule->cond,
3834 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3835 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003836 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003837 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003838 struct switching_rule *rule;
3839
Willy Tarreaub099aca2008-10-12 17:26:37 +02003840 if (curproxy == &defproxy) {
3841 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003844 }
3845
Willy Tarreau55ea7572007-06-17 19:56:27 +02003846 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003848
3849 if (*(args[1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003853 }
3854
Willy Tarreauf51658d2014-04-23 01:21:56 +02003855 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3856 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3857 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3858 file, linenum, errmsg);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003862
Willy Tarreauf51658d2014-04-23 01:21:56 +02003863 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003864 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003865 else if (*args[2]) {
3866 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3867 file, linenum, args[2]);
3868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
3870 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003871
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003872 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003873 if (!rule) {
3874 Alert("Out of memory error.\n");
3875 goto out;
3876 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003877 rule->cond = cond;
3878 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003879 rule->line = linenum;
3880 rule->file = strdup(file);
3881 if (!rule->file) {
3882 Alert("Out of memory error.\n");
3883 goto out;
3884 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003885 LIST_INIT(&rule->list);
3886 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3887 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003888 else if (strcmp(args[0], "use-server") == 0) {
3889 struct server_rule *rule;
3890
3891 if (curproxy == &defproxy) {
3892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896
3897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3898 err_code |= ERR_WARN;
3899
3900 if (*(args[1]) == 0) {
3901 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
3904 }
3905
3906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3907 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3908 file, linenum, args[0]);
3909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
3911 }
3912
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3914 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3915 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003920 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003921
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003922 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003923 rule->cond = cond;
3924 rule->srv.name = strdup(args[1]);
3925 LIST_INIT(&rule->list);
3926 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3927 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3928 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003929 else if ((!strcmp(args[0], "force-persist")) ||
3930 (!strcmp(args[0], "ignore-persist"))) {
3931 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003932
3933 if (curproxy == &defproxy) {
3934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
3939 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3940 err_code |= ERR_WARN;
3941
Willy Tarreauef6494c2010-01-28 17:12:36 +01003942 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003943 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3944 file, linenum, args[0]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003949 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3950 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3951 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
3954 }
3955
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003956 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3957 * where force-persist is applied.
3958 */
3959 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003960
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003961 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003962 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003963 if (!strcmp(args[0], "force-persist")) {
3964 rule->type = PERSIST_TYPE_FORCE;
3965 } else {
3966 rule->type = PERSIST_TYPE_IGNORE;
3967 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003968 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003969 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003970 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003971 else if (!strcmp(args[0], "stick-table")) {
3972 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003973 struct proxy *other;
3974
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003975 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003976 if (other) {
3977 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3978 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982
Emeric Brun32da3c42010-09-23 18:39:19 +02003983 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003984 curproxy->table.type = (unsigned int)-1;
3985 while (*args[myidx]) {
3986 const char *err;
3987
3988 if (strcmp(args[myidx], "size") == 0) {
3989 myidx++;
3990 if (!*(args[myidx])) {
3991 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3992 file, linenum, args[myidx-1]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3997 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3998 file, linenum, *err, args[myidx-1]);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004002 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004003 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004004 else if (strcmp(args[myidx], "peers") == 0) {
4005 myidx++;
Godbach50523162013-12-11 19:48:57 +08004006 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004007 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4008 file, linenum, args[myidx-1]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Godbach50523162013-12-11 19:48:57 +08004011 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004012 curproxy->table.peers.name = strdup(args[myidx++]);
4013 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004014 else if (strcmp(args[myidx], "expire") == 0) {
4015 myidx++;
4016 if (!*(args[myidx])) {
4017 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;
4021 }
4022 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4023 if (err) {
4024 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4025 file, linenum, *err, args[myidx-1]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004029 if (val > INT_MAX) {
4030 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4031 file, linenum, val);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004035 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004036 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004037 }
4038 else if (strcmp(args[myidx], "nopurge") == 0) {
4039 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004040 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004041 }
4042 else if (strcmp(args[myidx], "type") == 0) {
4043 myidx++;
4044 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4045 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4046 file, linenum, args[myidx]);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004050 /* myidx already points to next arg */
4051 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004052 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004053 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004054 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004055
4056 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004057 nw = args[myidx];
4058 while (*nw) {
4059 /* the "store" keyword supports a comma-separated list */
4060 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004061 sa = NULL; /* store arg */
4062 while (*nw && *nw != ',') {
4063 if (*nw == '(') {
4064 *nw = 0;
4065 sa = ++nw;
4066 while (*nw != ')') {
4067 if (!*nw) {
4068 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4069 file, linenum, args[0], cw);
4070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
4073 nw++;
4074 }
4075 *nw = '\0';
4076 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004077 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004078 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004079 if (*nw)
4080 *nw++ = '\0';
4081 type = stktable_get_data_type(cw);
4082 if (type < 0) {
4083 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4084 file, linenum, args[0], cw);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
Willy Tarreauac782882010-06-20 10:41:54 +02004088
4089 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4090 switch (err) {
4091 case PE_NONE: break;
4092 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004093 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4094 file, linenum, args[0], cw);
4095 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004096 break;
4097
4098 case PE_ARG_MISSING:
4099 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4100 file, linenum, args[0], cw);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103
4104 case PE_ARG_NOT_USED:
4105 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4106 file, linenum, args[0], cw);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109
4110 default:
4111 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4112 file, linenum, args[0], cw);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004115 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004116 }
4117 myidx++;
4118 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004119 else {
4120 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4121 file, linenum, args[myidx]);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 }
4126
4127 if (!curproxy->table.size) {
4128 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4129 file, linenum);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133
4134 if (curproxy->table.type == (unsigned int)-1) {
4135 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4136 file, linenum);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140 }
4141 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004142 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004143 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004144 int myidx = 0;
4145 const char *name = NULL;
4146 int flags;
4147
4148 if (curproxy == &defproxy) {
4149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
4152 }
4153
4154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4155 err_code |= ERR_WARN;
4156 goto out;
4157 }
4158
4159 myidx++;
4160 if ((strcmp(args[myidx], "store") == 0) ||
4161 (strcmp(args[myidx], "store-request") == 0)) {
4162 myidx++;
4163 flags = STK_IS_STORE;
4164 }
4165 else if (strcmp(args[myidx], "store-response") == 0) {
4166 myidx++;
4167 flags = STK_IS_STORE | STK_ON_RSP;
4168 }
4169 else if (strcmp(args[myidx], "match") == 0) {
4170 myidx++;
4171 flags = STK_IS_MATCH;
4172 }
4173 else if (strcmp(args[myidx], "on") == 0) {
4174 myidx++;
4175 flags = STK_IS_MATCH | STK_IS_STORE;
4176 }
4177 else {
4178 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
4182
4183 if (*(args[myidx]) == 0) {
4184 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004189 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004190 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004191 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004192 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
4197 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004198 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4199 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4200 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004201 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004202 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004203 goto out;
4204 }
4205 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004206 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4207 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4208 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004209 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004210 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004211 goto out;
4212 }
4213 }
4214
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004215 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004216 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004217
Emeric Brunb982a3d2010-01-04 15:45:53 +01004218 if (strcmp(args[myidx], "table") == 0) {
4219 myidx++;
4220 name = args[myidx++];
4221 }
4222
Willy Tarreauef6494c2010-01-28 17:12:36 +01004223 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004224 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4225 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4226 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004227 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004228 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004229 goto out;
4230 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004231 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004232 else if (*(args[myidx])) {
4233 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4234 file, linenum, args[0], args[myidx]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004236 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004237 goto out;
4238 }
Emeric Brun97679e72010-09-23 17:56:44 +02004239 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004240 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004241 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004242 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004243
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004244 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004245 rule->cond = cond;
4246 rule->expr = expr;
4247 rule->flags = flags;
4248 rule->table.name = name ? strdup(name) : NULL;
4249 LIST_INIT(&rule->list);
4250 if (flags & STK_ON_RSP)
4251 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4252 else
4253 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 else if (!strcmp(args[0], "stats")) {
4256 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4257 curproxy->uri_auth = NULL; /* we must detach from the default config */
4258
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004259 if (!*args[1]) {
4260 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004261 } else if (!strcmp(args[1], "admin")) {
4262 struct stats_admin_rule *rule;
4263
4264 if (curproxy == &defproxy) {
4265 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
4270 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4271 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4272 err_code |= ERR_ALERT | ERR_ABORT;
4273 goto out;
4274 }
4275
4276 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4277 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4278 file, linenum, args[0], args[1]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004282 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4283 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4284 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
4288
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004289 err_code |= warnif_cond_conflicts(cond,
4290 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4291 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004292
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004293 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004294 rule->cond = cond;
4295 LIST_INIT(&rule->list);
4296 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 } else if (!strcmp(args[1], "uri")) {
4298 if (*(args[2]) == 0) {
4299 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004302 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4303 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_ABORT;
4305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 }
4307 } else if (!strcmp(args[1], "realm")) {
4308 if (*(args[2]) == 0) {
4309 Alert("parsing [%s:%d] : 'realm' needs an realm name.\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_realm(&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 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004317 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004318 unsigned interval;
4319
4320 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4321 if (err) {
4322 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4323 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004326 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_ABORT;
4329 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004330 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004331 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004332 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004333
4334 if (curproxy == &defproxy) {
4335 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339
4340 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4341 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
4344 }
4345
Willy Tarreauff011f22011-01-06 17:51:27 +01004346 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004347 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004348 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4349 file, linenum, args[0]);
4350 err_code |= ERR_WARN;
4351 }
4352
Willy Tarreauff011f22011-01-06 17:51:27 +01004353 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004354
Willy Tarreauff011f22011-01-06 17:51:27 +01004355 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004356 err_code |= ERR_ALERT | ERR_ABORT;
4357 goto out;
4358 }
4359
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004360 err_code |= warnif_cond_conflicts(rule->cond,
4361 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4362 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004363 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004364
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 } else if (!strcmp(args[1], "auth")) {
4366 if (*(args[2]) == 0) {
4367 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_ALERT | ERR_ABORT;
4373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 }
4375 } else if (!strcmp(args[1], "scope")) {
4376 if (*(args[2]) == 0) {
4377 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\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_scope(&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], "enable")) {
4386 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_ABORT;
4389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004391 } else if (!strcmp(args[1], "hide-version")) {
4392 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4393 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_ABORT;
4395 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004396 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004397 } else if (!strcmp(args[1], "show-legends")) {
4398 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4399 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4400 err_code |= ERR_ALERT | ERR_ABORT;
4401 goto out;
4402 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004403 } else if (!strcmp(args[1], "show-node")) {
4404
4405 if (*args[2]) {
4406 int i;
4407 char c;
4408
4409 for (i=0; args[2][i]; i++) {
4410 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004411 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4412 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004413 break;
4414 }
4415
4416 if (!i || args[2][i]) {
4417 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4418 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4419 file, linenum, args[0], args[1]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423 }
4424
4425 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4426 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4427 err_code |= ERR_ALERT | ERR_ABORT;
4428 goto out;
4429 }
4430 } else if (!strcmp(args[1], "show-desc")) {
4431 char *desc = NULL;
4432
4433 if (*args[2]) {
4434 int i, len=0;
4435 char *d;
4436
Willy Tarreau348acfe2014-04-14 15:00:39 +02004437 for (i = 2; *args[i]; i++)
4438 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004439
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004440 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004441
Willy Tarreau348acfe2014-04-14 15:00:39 +02004442 d += snprintf(d, desc + len - d, "%s", args[2]);
4443 for (i = 3; *args[i]; i++)
4444 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004445 }
4446
4447 if (!*args[2] && !global.desc)
4448 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4449 file, linenum, args[1]);
4450 else {
4451 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4452 free(desc);
4453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4454 err_code |= ERR_ALERT | ERR_ABORT;
4455 goto out;
4456 }
4457 free(desc);
4458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004460stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004461 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 +01004462 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 }
4466 }
4467 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004468 int optnum;
4469
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004470 if (*(args[1]) == '\0') {
4471 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4472 file, linenum, args[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 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004476
4477 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4478 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004479 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4480 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4481 file, linenum, cfg_opts[optnum].name);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004485 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4486 goto out;
4487
Willy Tarreau93893792009-07-23 13:19:11 +02004488 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4489 err_code |= ERR_WARN;
4490 goto out;
4491 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004492
Willy Tarreau3842f002009-06-14 11:39:52 +02004493 curproxy->no_options &= ~cfg_opts[optnum].val;
4494 curproxy->options &= ~cfg_opts[optnum].val;
4495
4496 switch (kwm) {
4497 case KWM_STD:
4498 curproxy->options |= cfg_opts[optnum].val;
4499 break;
4500 case KWM_NO:
4501 curproxy->no_options |= cfg_opts[optnum].val;
4502 break;
4503 case KWM_DEF: /* already cleared */
4504 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004505 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004506
Willy Tarreau93893792009-07-23 13:19:11 +02004507 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004508 }
4509 }
4510
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004511 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4512 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004513 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4514 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4515 file, linenum, cfg_opts2[optnum].name);
4516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
4518 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004519 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4520 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004521 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4522 err_code |= ERR_WARN;
4523 goto out;
4524 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004525
Willy Tarreau3842f002009-06-14 11:39:52 +02004526 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4527 curproxy->options2 &= ~cfg_opts2[optnum].val;
4528
4529 switch (kwm) {
4530 case KWM_STD:
4531 curproxy->options2 |= cfg_opts2[optnum].val;
4532 break;
4533 case KWM_NO:
4534 curproxy->no_options2 |= cfg_opts2[optnum].val;
4535 break;
4536 case KWM_DEF: /* already cleared */
4537 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004538 }
Willy Tarreau93893792009-07-23 13:19:11 +02004539 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004540 }
4541 }
4542
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004543 /* HTTP options override each other. They can be cancelled using
4544 * "no option xxx" which only switches to default mode if the mode
4545 * was this one (useful for cancelling options set in defaults
4546 * sections).
4547 */
4548 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004549 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4550 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004551 if (kwm == KWM_STD) {
4552 curproxy->options &= ~PR_O_HTTP_MODE;
4553 curproxy->options |= PR_O_HTTP_PCL;
4554 goto out;
4555 }
4556 else if (kwm == KWM_NO) {
4557 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4558 curproxy->options &= ~PR_O_HTTP_MODE;
4559 goto out;
4560 }
4561 }
4562 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004563 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4564 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004565 if (kwm == KWM_STD) {
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 curproxy->options |= PR_O_HTTP_FCL;
4568 goto out;
4569 }
4570 else if (kwm == KWM_NO) {
4571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4572 curproxy->options &= ~PR_O_HTTP_MODE;
4573 goto out;
4574 }
4575 }
4576 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004577 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4578 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004579 if (kwm == KWM_STD) {
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 curproxy->options |= PR_O_HTTP_SCL;
4582 goto out;
4583 }
4584 else if (kwm == KWM_NO) {
4585 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4586 curproxy->options &= ~PR_O_HTTP_MODE;
4587 goto out;
4588 }
4589 }
4590 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004593 if (kwm == KWM_STD) {
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 curproxy->options |= PR_O_HTTP_KAL;
4596 goto out;
4597 }
4598 else if (kwm == KWM_NO) {
4599 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4600 curproxy->options &= ~PR_O_HTTP_MODE;
4601 goto out;
4602 }
4603 }
4604 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004605 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4606 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004607 if (kwm == KWM_STD) {
4608 curproxy->options &= ~PR_O_HTTP_MODE;
4609 curproxy->options |= PR_O_HTTP_TUN;
4610 goto out;
4611 }
4612 else if (kwm == KWM_NO) {
4613 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4614 curproxy->options &= ~PR_O_HTTP_MODE;
4615 goto out;
4616 }
4617 }
4618
Joseph Lynch726ab712015-05-11 23:25:34 -07004619 /* Redispatch can take an integer argument that control when the
4620 * resispatch occurs. All values are relative to the retries option.
4621 * This can be cancelled using "no option xxx".
4622 */
4623 if (strcmp(args[1], "redispatch") == 0) {
4624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4625 err_code |= ERR_WARN;
4626 goto out;
4627 }
4628
4629 curproxy->no_options &= ~PR_O_REDISP;
4630 curproxy->options &= ~PR_O_REDISP;
4631
4632 switch (kwm) {
4633 case KWM_STD:
4634 curproxy->options |= PR_O_REDISP;
4635 curproxy->redispatch_after = -1;
4636 if(*args[2]) {
4637 curproxy->redispatch_after = atol(args[2]);
4638 }
4639 break;
4640 case KWM_NO:
4641 curproxy->no_options |= PR_O_REDISP;
4642 curproxy->redispatch_after = 0;
4643 break;
4644 case KWM_DEF: /* already cleared */
4645 break;
4646 }
4647 goto out;
4648 }
4649
Willy Tarreau3842f002009-06-14 11:39:52 +02004650 if (kwm != KWM_STD) {
4651 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004652 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004655 }
4656
Emeric Brun3a058f32009-06-30 18:26:00 +02004657 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004658 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004660 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004661 if (*(args[2]) != '\0') {
4662 if (!strcmp(args[2], "clf")) {
4663 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004664 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004665 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004666 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004669 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004670 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4671 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004672 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004673 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4674 char *oldlogformat = "log-format";
4675 char *clflogformat = "";
4676
4677 if (curproxy->conf.logformat_string == default_http_log_format)
4678 oldlogformat = "option httplog";
4679 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4680 oldlogformat = "option tcplog";
4681 else if (curproxy->conf.logformat_string == clf_http_log_format)
4682 oldlogformat = "option httplog clf";
4683 if (logformat == clf_http_log_format)
4684 clflogformat = " clf";
4685 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4686 file, linenum, clflogformat, oldlogformat);
4687 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004688 if (curproxy->conf.logformat_string != default_http_log_format &&
4689 curproxy->conf.logformat_string != default_tcp_log_format &&
4690 curproxy->conf.logformat_string != clf_http_log_format)
4691 free(curproxy->conf.logformat_string);
4692 curproxy->conf.logformat_string = logformat;
4693
4694 free(curproxy->conf.lfs_file);
4695 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4696 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004697 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004698 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004699 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4700 char *oldlogformat = "log-format";
4701
4702 if (curproxy->conf.logformat_string == default_http_log_format)
4703 oldlogformat = "option httplog";
4704 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4705 oldlogformat = "option tcplog";
4706 else if (curproxy->conf.logformat_string == clf_http_log_format)
4707 oldlogformat = "option httplog clf";
4708 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4709 file, linenum, oldlogformat);
4710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004712 if (curproxy->conf.logformat_string != default_http_log_format &&
4713 curproxy->conf.logformat_string != default_tcp_log_format &&
4714 curproxy->conf.logformat_string != clf_http_log_format)
4715 free(curproxy->conf.logformat_string);
4716 curproxy->conf.logformat_string = default_tcp_log_format;
4717
4718 free(curproxy->conf.lfs_file);
4719 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4720 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004721
4722 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4723 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004726 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004727 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004728 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004729
William Lallemanddf1425a2015-04-28 20:17:49 +02004730 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4731 goto out;
4732
Willy Tarreau13943ab2006-12-31 00:24:10 +01004733 if (curproxy->cap & PR_CAP_FE)
4734 curproxy->options |= PR_O_TCP_CLI_KA;
4735 if (curproxy->cap & PR_CAP_BE)
4736 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 }
4738 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_WARN;
4741
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004743 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004744 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004745 curproxy->options2 &= ~PR_O2_CHK_ANY;
4746 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 if (!*args[2]) { /* no argument */
4748 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4749 curproxy->check_len = strlen(DEF_CHECK_REQ);
4750 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004751 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004752 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004754 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004756 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 if (*args[4])
4758 reqlen += strlen(args[4]);
4759 else
4760 reqlen += strlen("HTTP/1.0");
4761
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 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004766 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4767 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004768 }
4769 else if (!strcmp(args[1], "ssl-hello-chk")) {
4770 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004771 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004772 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004773
Willy Tarreaua534fea2008-08-03 12:19:50 +02004774 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004775 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004776 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004777 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004778
4779 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
Willy Tarreau23677902007-05-08 23:50:35 +02004782 else if (!strcmp(args[1], "smtpchk")) {
4783 /* use SMTP request to check servers' health */
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;
4787 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004788
4789 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4790 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4791 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4792 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4793 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4794 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004795 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004796 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4797 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4798 } else {
4799 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4800 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4801 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4802 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4803 }
4804 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004805 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4806 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004807 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004808 else if (!strcmp(args[1], "pgsql-check")) {
4809 /* use PostgreSQL request to check servers' health */
4810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4811 err_code |= ERR_WARN;
4812
4813 free(curproxy->check_req);
4814 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004815 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004816 curproxy->options2 |= PR_O2_PGSQL_CHK;
4817
4818 if (*(args[2])) {
4819 int cur_arg = 2;
4820
4821 while (*(args[cur_arg])) {
4822 if (strcmp(args[cur_arg], "user") == 0) {
4823 char * packet;
4824 uint32_t packet_len;
4825 uint32_t pv;
4826
4827 /* suboption header - needs additional argument for it */
4828 if (*(args[cur_arg+1]) == 0) {
4829 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4830 file, linenum, args[0], args[1], args[cur_arg]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
4834
4835 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4836 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4837 pv = htonl(0x30000); /* protocol version 3.0 */
4838
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004839 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004840
4841 memcpy(packet + 4, &pv, 4);
4842
4843 /* copy "user" */
4844 memcpy(packet + 8, "user", 4);
4845
4846 /* copy username */
4847 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4848
4849 free(curproxy->check_req);
4850 curproxy->check_req = packet;
4851 curproxy->check_len = packet_len;
4852
4853 packet_len = htonl(packet_len);
4854 memcpy(packet, &packet_len, 4);
4855 cur_arg += 2;
4856 } else {
4857 /* unknown suboption - catchall */
4858 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4859 file, linenum, args[0], args[1]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 } /* end while loop */
4864 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004865 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4866 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004867 }
4868
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004869 else if (!strcmp(args[1], "redis-check")) {
4870 /* use REDIS PING request to check servers' health */
4871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4872 err_code |= ERR_WARN;
4873
4874 free(curproxy->check_req);
4875 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004876 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004877 curproxy->options2 |= PR_O2_REDIS_CHK;
4878
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004879 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004880 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4881 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004882
4883 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4884 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004885 }
4886
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004887 else if (!strcmp(args[1], "mysql-check")) {
4888 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004889 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4890 err_code |= ERR_WARN;
4891
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004892 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004893 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004894 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004895 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004896
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004897 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004898 * const char mysql40_client_auth_pkt[] = {
4899 * "\x0e\x00\x00" // packet length
4900 * "\x01" // packet number
4901 * "\x00\x00" // client capabilities
4902 * "\x00\x00\x01" // max packet
4903 * "haproxy\x00" // username (null terminated string)
4904 * "\x00" // filler (always 0x00)
4905 * "\x01\x00\x00" // packet length
4906 * "\x00" // packet number
4907 * "\x01" // COM_QUIT command
4908 * };
4909 */
4910
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004911 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4912 * const char mysql41_client_auth_pkt[] = {
4913 * "\x0e\x00\x00\" // packet length
4914 * "\x01" // packet number
4915 * "\x00\x00\x00\x00" // client capabilities
4916 * "\x00\x00\x00\x01" // max packet
4917 * "\x21" // character set (UTF-8)
4918 * char[23] // All zeroes
4919 * "haproxy\x00" // username (null terminated string)
4920 * "\x00" // filler (always 0x00)
4921 * "\x01\x00\x00" // packet length
4922 * "\x00" // packet number
4923 * "\x01" // COM_QUIT command
4924 * };
4925 */
4926
4927
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004928 if (*(args[2])) {
4929 int cur_arg = 2;
4930
4931 while (*(args[cur_arg])) {
4932 if (strcmp(args[cur_arg], "user") == 0) {
4933 char *mysqluser;
4934 int packetlen, reqlen, userlen;
4935
4936 /* suboption header - needs additional argument for it */
4937 if (*(args[cur_arg+1]) == 0) {
4938 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4939 file, linenum, args[0], args[1], args[cur_arg]);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943 mysqluser = args[cur_arg + 1];
4944 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004945
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004946 if (*(args[cur_arg+2])) {
4947 if (!strcmp(args[cur_arg+2], "post-41")) {
4948 packetlen = userlen + 7 + 27;
4949 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004950
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004951 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004952 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004953 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004954
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004955 snprintf(curproxy->check_req, 4, "%c%c%c",
4956 ((unsigned char) packetlen & 0xff),
4957 ((unsigned char) (packetlen >> 8) & 0xff),
4958 ((unsigned char) (packetlen >> 16) & 0xff));
4959
4960 curproxy->check_req[3] = 1;
4961 curproxy->check_req[5] = 130;
4962 curproxy->check_req[11] = 1;
4963 curproxy->check_req[12] = 33;
4964 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4965 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4966 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4967 cur_arg += 3;
4968 } else {
4969 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
4973 } else {
4974 packetlen = userlen + 7;
4975 reqlen = packetlen + 9;
4976
4977 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004978 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004979 curproxy->check_len = reqlen;
4980
4981 snprintf(curproxy->check_req, 4, "%c%c%c",
4982 ((unsigned char) packetlen & 0xff),
4983 ((unsigned char) (packetlen >> 8) & 0xff),
4984 ((unsigned char) (packetlen >> 16) & 0xff));
4985
4986 curproxy->check_req[3] = 1;
4987 curproxy->check_req[5] = 128;
4988 curproxy->check_req[8] = 1;
4989 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4990 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4991 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4992 cur_arg += 2;
4993 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004994 } else {
4995 /* unknown suboption - catchall */
4996 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4997 file, linenum, args[0], args[1]);
4998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
5000 }
5001 } /* end while loop */
5002 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005003 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005004 else if (!strcmp(args[1], "ldap-check")) {
5005 /* use LDAP request to check servers' health */
5006 free(curproxy->check_req);
5007 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005008 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005009 curproxy->options2 |= PR_O2_LDAP_CHK;
5010
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005011 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005012 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5013 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005014 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5015 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005016 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005017 else if (!strcmp(args[1], "spop-check")) {
5018 if (curproxy == &defproxy) {
5019 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5020 file, linenum, args[0], args[1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024 if (curproxy->cap & PR_CAP_FE) {
5025 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5026 file, linenum, args[0], args[1]);
5027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029 }
5030
5031 /* use SPOE request to check servers' health */
5032 free(curproxy->check_req);
5033 curproxy->check_req = NULL;
5034 curproxy->options2 &= ~PR_O2_CHK_ANY;
5035 curproxy->options2 |= PR_O2_SPOP_CHK;
5036
Christopher Faulet8ef75252017-02-20 22:56:03 +01005037 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005038 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
5042 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5043 goto out;
5044 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005045 else if (!strcmp(args[1], "tcp-check")) {
5046 /* use raw TCPCHK send/expect to check servers' health */
5047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5048 err_code |= ERR_WARN;
5049
5050 free(curproxy->check_req);
5051 curproxy->check_req = NULL;
5052 curproxy->options2 &= ~PR_O2_CHK_ANY;
5053 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005054 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5055 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005056 }
Simon Horman98637e52014-06-20 12:30:16 +09005057 else if (!strcmp(args[1], "external-check")) {
5058 /* excute an external command to check servers' health */
5059 free(curproxy->check_req);
5060 curproxy->check_req = NULL;
5061 curproxy->options2 &= ~PR_O2_CHK_ANY;
5062 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005063 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5064 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005065 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005066 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005067 int cur_arg;
5068
5069 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5070 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005071 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005072
Willy Tarreau87cf5142011-08-19 22:57:24 +02005073 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005074
5075 free(curproxy->fwdfor_hdr_name);
5076 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5077 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5078
5079 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5080 cur_arg = 2;
5081 while (*(args[cur_arg])) {
5082 if (!strcmp(args[cur_arg], "except")) {
5083 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005084 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005085 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5086 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005089 }
5090 /* flush useless bits */
5091 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005092 cur_arg += 2;
5093 } else if (!strcmp(args[cur_arg], "header")) {
5094 /* suboption header - needs additional argument for it */
5095 if (*(args[cur_arg+1]) == 0) {
5096 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005100 }
5101 free(curproxy->fwdfor_hdr_name);
5102 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5103 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5104 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005105 } else if (!strcmp(args[cur_arg], "if-none")) {
5106 curproxy->options &= ~PR_O_FF_ALWAYS;
5107 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005108 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005109 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005110 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005111 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005114 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005115 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005116 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005117 else if (!strcmp(args[1], "originalto")) {
5118 int cur_arg;
5119
5120 /* insert x-original-to field, but not for the IP address listed as an except.
5121 * set default options (ie: bitfield, header name, etc)
5122 */
5123
5124 curproxy->options |= PR_O_ORGTO;
5125
5126 free(curproxy->orgto_hdr_name);
5127 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5128 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5129
Willy Tarreau87cf5142011-08-19 22:57:24 +02005130 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005131 cur_arg = 2;
5132 while (*(args[cur_arg])) {
5133 if (!strcmp(args[cur_arg], "except")) {
5134 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005135 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 +02005136 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5137 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005140 }
5141 /* flush useless bits */
5142 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5143 cur_arg += 2;
5144 } else if (!strcmp(args[cur_arg], "header")) {
5145 /* suboption header - needs additional argument for it */
5146 if (*(args[cur_arg+1]) == 0) {
5147 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005151 }
5152 free(curproxy->orgto_hdr_name);
5153 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5154 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5155 cur_arg += 2;
5156 } else {
5157 /* unknown suboption - catchall */
5158 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5159 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005162 }
5163 } /* end while loop */
5164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 else {
5166 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
Willy Tarreau93893792009-07-23 13:19:11 +02005170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005172 else if (!strcmp(args[0], "default_backend")) {
5173 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005175
5176 if (*(args[1]) == 0) {
5177 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005180 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005181 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005182 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005183
5184 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5185 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005186 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005188 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005190
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005191 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5192 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 +01005193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 /* enable reconnections to dispatch */
5196 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005197
5198 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005201 else if (!strcmp(args[0], "http-reuse")) {
5202 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5203 err_code |= ERR_WARN;
5204
5205 if (strcmp(args[1], "never") == 0) {
5206 /* enable a graceful server shutdown on an HTTP 404 response */
5207 curproxy->options &= ~PR_O_REUSE_MASK;
5208 curproxy->options |= PR_O_REUSE_NEVR;
5209 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5210 goto out;
5211 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005212 else if (strcmp(args[1], "safe") == 0) {
5213 /* enable a graceful server shutdown on an HTTP 404 response */
5214 curproxy->options &= ~PR_O_REUSE_MASK;
5215 curproxy->options |= PR_O_REUSE_SAFE;
5216 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5217 goto out;
5218 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005219 else if (strcmp(args[1], "aggressive") == 0) {
5220 curproxy->options &= ~PR_O_REUSE_MASK;
5221 curproxy->options |= PR_O_REUSE_AGGR;
5222 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5223 goto out;
5224 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005225 else if (strcmp(args[1], "always") == 0) {
5226 /* enable a graceful server shutdown on an HTTP 404 response */
5227 curproxy->options &= ~PR_O_REUSE_MASK;
5228 curproxy->options |= PR_O_REUSE_ALWS;
5229 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5230 goto out;
5231 }
5232 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005233 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005238 else if (!strcmp(args[0], "http-check")) {
5239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005241
5242 if (strcmp(args[1], "disable-on-404") == 0) {
5243 /* enable a graceful server shutdown on an HTTP 404 response */
5244 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005245 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5246 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005247 }
Willy Tarreauef781042010-01-27 11:53:01 +01005248 else if (strcmp(args[1], "send-state") == 0) {
5249 /* enable emission of the apparent state of a server in HTTP checks */
5250 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005251 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5252 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005253 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005254 else if (strcmp(args[1], "expect") == 0) {
5255 const char *ptr_arg;
5256 int cur_arg;
5257
5258 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5259 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
5263
5264 cur_arg = 2;
5265 /* consider exclamation marks, sole or at the beginning of a word */
5266 while (*(ptr_arg = args[cur_arg])) {
5267 while (*ptr_arg == '!') {
5268 curproxy->options2 ^= PR_O2_EXP_INV;
5269 ptr_arg++;
5270 }
5271 if (*ptr_arg)
5272 break;
5273 cur_arg++;
5274 }
5275 /* now ptr_arg points to the beginning of a word past any possible
5276 * exclamation mark, and cur_arg is the argument which holds this word.
5277 */
5278 if (strcmp(ptr_arg, "status") == 0) {
5279 if (!*(args[cur_arg + 1])) {
5280 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5281 file, linenum, args[0], args[1], ptr_arg);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005286 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005287 curproxy->expect_str = strdup(args[cur_arg + 1]);
5288 }
5289 else if (strcmp(ptr_arg, "string") == 0) {
5290 if (!*(args[cur_arg + 1])) {
5291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5292 file, linenum, args[0], args[1], ptr_arg);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005298 curproxy->expect_str = strdup(args[cur_arg + 1]);
5299 }
5300 else if (strcmp(ptr_arg, "rstatus") == 0) {
5301 if (!*(args[cur_arg + 1])) {
5302 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5303 file, linenum, args[0], args[1], ptr_arg);
5304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
5306 }
5307 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005308 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005309 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005310 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005311 free(curproxy->expect_regex);
5312 curproxy->expect_regex = NULL;
5313 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005314 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005315 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5316 error = NULL;
5317 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5318 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5319 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5320 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324 }
5325 else if (strcmp(ptr_arg, "rstring") == 0) {
5326 if (!*(args[cur_arg + 1])) {
5327 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5328 file, linenum, args[0], args[1], ptr_arg);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005333 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005334 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005335 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005336 free(curproxy->expect_regex);
5337 curproxy->expect_regex = NULL;
5338 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005339 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005340 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5341 error = NULL;
5342 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5343 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5344 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5345 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349 }
5350 else {
5351 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5352 file, linenum, args[0], args[1], ptr_arg);
5353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005357 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005358 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 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005361 }
5362 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005363 else if (!strcmp(args[0], "tcp-check")) {
5364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5365 err_code |= ERR_WARN;
5366
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005367 if (strcmp(args[1], "comment") == 0) {
5368 int cur_arg;
5369 struct tcpcheck_rule *tcpcheck;
5370
5371 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005372 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005373 tcpcheck->action = TCPCHK_ACT_COMMENT;
5374
5375 if (!*args[cur_arg + 1]) {
5376 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5377 file, linenum, args[cur_arg]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381
5382 tcpcheck->comment = strdup(args[cur_arg + 1]);
5383
5384 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005385 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5386 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005387 }
5388 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005389 const char *ptr_arg;
5390 int cur_arg;
5391 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005392
5393 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005394 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5395 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5396 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5397 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5398 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005399
Willy Tarreau5581c272015-05-13 12:24:53 +02005400 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5401 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5402 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5403 file, linenum);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005406 }
5407
5408 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005409 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005410 tcpcheck->action = TCPCHK_ACT_CONNECT;
5411
5412 /* parsing each parameters to fill up the rule */
5413 while (*(ptr_arg = args[cur_arg])) {
5414 /* tcp port */
5415 if (strcmp(args[cur_arg], "port") == 0) {
5416 if ( (atol(args[cur_arg + 1]) > 65535) ||
5417 (atol(args[cur_arg + 1]) < 1) ){
5418 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5419 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
5423 tcpcheck->port = atol(args[cur_arg + 1]);
5424 cur_arg += 2;
5425 }
5426 /* send proxy protocol */
5427 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5428 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5429 cur_arg++;
5430 }
5431#ifdef USE_OPENSSL
5432 else if (strcmp(args[cur_arg], "ssl") == 0) {
5433 curproxy->options |= PR_O_TCPCHK_SSL;
5434 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5435 cur_arg++;
5436 }
5437#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005438 /* comment for this tcpcheck line */
5439 else if (strcmp(args[cur_arg], "comment") == 0) {
5440 if (!*args[cur_arg + 1]) {
5441 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5442 file, linenum, args[cur_arg]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446 tcpcheck->comment = strdup(args[cur_arg + 1]);
5447 cur_arg += 2;
5448 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005449 else {
5450#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005451 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 +01005452#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005453 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 +01005454#endif /* USE_OPENSSL */
5455 file, linenum, args[0], args[1], args[cur_arg]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
5459
5460 }
5461
5462 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5463 }
5464 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005465 if (! *(args[2]) ) {
5466 /* SEND string expected */
5467 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5468 file, linenum, args[0], args[1], args[2]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 } else {
5472 struct tcpcheck_rule *tcpcheck;
5473
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005474 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005475
5476 tcpcheck->action = TCPCHK_ACT_SEND;
5477 tcpcheck->string_len = strlen(args[2]);
5478 tcpcheck->string = strdup(args[2]);
5479 tcpcheck->expect_regex = NULL;
5480
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005481 /* comment for this tcpcheck line */
5482 if (strcmp(args[3], "comment") == 0) {
5483 if (!*args[4]) {
5484 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5485 file, linenum, args[3]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
5489 tcpcheck->comment = strdup(args[4]);
5490 }
5491
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005492 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5493 }
5494 }
5495 else if (strcmp(args[1], "send-binary") == 0) {
5496 if (! *(args[2]) ) {
5497 /* SEND binary string expected */
5498 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5499 file, linenum, args[0], args[1], args[2]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 } else {
5503 struct tcpcheck_rule *tcpcheck;
5504 char *err = NULL;
5505
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005506 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005507
5508 tcpcheck->action = TCPCHK_ACT_SEND;
5509 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5510 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5511 file, linenum, args[0], args[1], args[2], err);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 tcpcheck->expect_regex = NULL;
5516
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005517 /* comment for this tcpcheck line */
5518 if (strcmp(args[3], "comment") == 0) {
5519 if (!*args[4]) {
5520 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5521 file, linenum, args[3]);
5522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
5524 }
5525 tcpcheck->comment = strdup(args[4]);
5526 }
5527
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005528 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5529 }
5530 }
5531 else if (strcmp(args[1], "expect") == 0) {
5532 const char *ptr_arg;
5533 int cur_arg;
5534 int inverse = 0;
5535
5536 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5537 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
5541
5542 cur_arg = 2;
5543 /* consider exclamation marks, sole or at the beginning of a word */
5544 while (*(ptr_arg = args[cur_arg])) {
5545 while (*ptr_arg == '!') {
5546 inverse = !inverse;
5547 ptr_arg++;
5548 }
5549 if (*ptr_arg)
5550 break;
5551 cur_arg++;
5552 }
5553 /* now ptr_arg points to the beginning of a word past any possible
5554 * exclamation mark, and cur_arg is the argument which holds this word.
5555 */
5556 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005557 struct tcpcheck_rule *tcpcheck;
5558 char *err = NULL;
5559
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005560 if (!*(args[cur_arg + 1])) {
5561 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5562 file, linenum, args[0], args[1], ptr_arg);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005566
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005567 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568
5569 tcpcheck->action = TCPCHK_ACT_EXPECT;
5570 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5571 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5572 file, linenum, args[0], args[1], args[2], err);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
5576 tcpcheck->expect_regex = NULL;
5577 tcpcheck->inverse = inverse;
5578
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005579 /* tcpcheck comment */
5580 cur_arg += 2;
5581 if (strcmp(args[cur_arg], "comment") == 0) {
5582 if (!*args[cur_arg + 1]) {
5583 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5584 file, linenum, args[cur_arg + 1]);
5585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 }
5588 tcpcheck->comment = strdup(args[cur_arg + 1]);
5589 }
5590
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005591 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5592 }
5593 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005594 struct tcpcheck_rule *tcpcheck;
5595
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005596 if (!*(args[cur_arg + 1])) {
5597 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5598 file, linenum, args[0], args[1], ptr_arg);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005602
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005603 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005604
5605 tcpcheck->action = TCPCHK_ACT_EXPECT;
5606 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5607 tcpcheck->string = strdup(args[cur_arg + 1]);
5608 tcpcheck->expect_regex = NULL;
5609 tcpcheck->inverse = inverse;
5610
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005611 /* tcpcheck comment */
5612 cur_arg += 2;
5613 if (strcmp(args[cur_arg], "comment") == 0) {
5614 if (!*args[cur_arg + 1]) {
5615 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5616 file, linenum, args[cur_arg + 1]);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 }
5620 tcpcheck->comment = strdup(args[cur_arg + 1]);
5621 }
5622
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005623 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5624 }
5625 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005626 struct tcpcheck_rule *tcpcheck;
5627
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005628 if (!*(args[cur_arg + 1])) {
5629 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5630 file, linenum, args[0], args[1], ptr_arg);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005634
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005635 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005636
5637 tcpcheck->action = TCPCHK_ACT_EXPECT;
5638 tcpcheck->string_len = 0;
5639 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005640 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5641 error = NULL;
5642 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5643 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5644 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5645 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649 tcpcheck->inverse = inverse;
5650
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005651 /* tcpcheck comment */
5652 cur_arg += 2;
5653 if (strcmp(args[cur_arg], "comment") == 0) {
5654 if (!*args[cur_arg + 1]) {
5655 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5656 file, linenum, args[cur_arg + 1]);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660 tcpcheck->comment = strdup(args[cur_arg + 1]);
5661 }
5662
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005663 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5664 }
5665 else {
5666 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5667 file, linenum, args[0], args[1], ptr_arg);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671 }
5672 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005673 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005678 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005679 if (curproxy == &defproxy) {
5680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005681 err_code |= ERR_ALERT | ERR_FATAL;
5682 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005683 }
5684
Willy Tarreaub80c2302007-11-30 20:51:32 +01005685 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005687
5688 if (strcmp(args[1], "fail") == 0) {
5689 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005690 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005691 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5692 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005695 }
5696
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005697 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5698 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5699 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005702 }
5703 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5704 }
5705 else {
5706 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005709 }
5710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711#ifdef TPROXY
5712 else if (!strcmp(args[0], "transparent")) {
5713 /* enable transparent proxy connections */
5714 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005715 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
5718#endif
5719 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005720 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005722
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005732 else if (!strcmp(args[0], "backlog")) { /* backlog */
5733 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005735
5736 if (*(args[1]) == 0) {
5737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005740 }
5741 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5743 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005744 }
Willy Tarreau86034312006-12-29 00:10:33 +01005745 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005746 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005748
Willy Tarreau86034312006-12-29 00:10:33 +01005749 if (*(args[1]) == 0) {
5750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005753 }
5754 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005755 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5756 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5759 if (*(args[1]) == 0) {
5760 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005764 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5765 if (err) {
5766 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5767 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005770 }
5771 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
5775 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005776 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005777 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005778 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005779
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 if (curproxy == &defproxy) {
5781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005785 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005787
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005788 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005789 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005790 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005791 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005792 goto out;
5793 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005794
5795 proto = protocol_by_family(sk->ss_family);
5796 if (!proto || !proto->connect) {
5797 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5798 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
5802
5803 if (port1 != port2) {
5804 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5805 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_ALERT | ERR_FATAL;
5807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005809
5810 if (!port1) {
5811 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5812 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
5815 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005816
William Lallemanddf1425a2015-04-28 20:17:49 +02005817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5818 goto out;
5819
Willy Tarreaud5191e72010-02-09 20:50:45 +01005820 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005821 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
5823 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005826
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005827 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5828 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005829 err_code |= ERR_ALERT | ERR_FATAL;
5830 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005833 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005834 /**
5835 * The syntax for hash-type config element is
5836 * hash-type {map-based|consistent} [[<algo>] avalanche]
5837 *
5838 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5839 */
5840 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005841
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5843 err_code |= ERR_WARN;
5844
5845 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005846 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5847 }
5848 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005849 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5850 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005851 else if (strcmp(args[1], "avalanche") == 0) {
5852 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]);
5853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005855 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005856 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005857 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
5860 }
Bhaskar98634f02013-10-29 23:30:51 -04005861
5862 /* set the hash function to use */
5863 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005864 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005865 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005866
5867 /* if consistent with no argument, then avalanche modifier is also applied */
5868 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5869 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005870 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005871 /* set the hash function */
5872 if (!strcmp(args[2], "sdbm")) {
5873 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5874 }
5875 else if (!strcmp(args[2], "djb2")) {
5876 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005877 }
5878 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005879 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005880 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005881 else if (!strcmp(args[2], "crc32")) {
5882 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5883 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005884 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005885 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 -05005886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
5888 }
5889
5890 /* set the hash modifier */
5891 if (!strcmp(args[3], "avalanche")) {
5892 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5893 }
5894 else if (*args[3]) {
5895 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005899 }
William Lallemanda73203e2012-03-12 12:48:57 +01005900 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005901 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5902 if (*(args[1]) == 0) {
5903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5908 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5909 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
5912 }
5913 }
William Lallemanda73203e2012-03-12 12:48:57 +01005914 else if (strcmp(args[0], "unique-id-format") == 0) {
5915 if (!*(args[1])) {
5916 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
5919 }
William Lallemand3203ff42012-11-11 17:30:56 +01005920 if (*(args[2])) {
5921 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
5924 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005925 free(curproxy->conf.uniqueid_format_string);
5926 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005927
Willy Tarreau62a61232013-04-12 18:13:46 +02005928 free(curproxy->conf.uif_file);
5929 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5930 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005931 }
William Lallemanda73203e2012-03-12 12:48:57 +01005932
5933 else if (strcmp(args[0], "unique-id-header") == 0) {
5934 if (!*(args[1])) {
5935 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5936 err_code |= ERR_ALERT | ERR_FATAL;
5937 goto out;
5938 }
5939 free(curproxy->header_unique_id);
5940 curproxy->header_unique_id = strdup(args[1]);
5941 }
5942
William Lallemand723b73a2012-02-08 16:37:49 +01005943 else if (strcmp(args[0], "log-format") == 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 }
William Lallemand3203ff42012-11-11 17:30:56 +01005949 if (*(args[2])) {
5950 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5951 err_code |= ERR_ALERT | ERR_FATAL;
5952 goto out;
5953 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005954 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5955 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005956
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005957 if (curproxy->conf.logformat_string == default_http_log_format)
5958 oldlogformat = "option httplog";
5959 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5960 oldlogformat = "option tcplog";
5961 else if (curproxy->conf.logformat_string == clf_http_log_format)
5962 oldlogformat = "option httplog clf";
5963 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5964 file, linenum, oldlogformat);
5965 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005966 if (curproxy->conf.logformat_string != default_http_log_format &&
5967 curproxy->conf.logformat_string != default_tcp_log_format &&
5968 curproxy->conf.logformat_string != clf_http_log_format)
5969 free(curproxy->conf.logformat_string);
5970 curproxy->conf.logformat_string = strdup(args[1]);
5971
5972 free(curproxy->conf.lfs_file);
5973 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5974 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005975
5976 /* get a chance to improve log-format error reporting by
5977 * reporting the correct line-number when possible.
5978 */
5979 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5980 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5981 file, linenum, curproxy->id);
5982 err_code |= ERR_WARN;
5983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005985 else if (!strcmp(args[0], "log-format-sd")) {
5986 if (!*(args[1])) {
5987 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5988 err_code |= ERR_ALERT | ERR_FATAL;
5989 goto out;
5990 }
5991 if (*(args[2])) {
5992 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996
5997 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5998 free(curproxy->conf.logformat_sd_string);
5999 curproxy->conf.logformat_sd_string = strdup(args[1]);
6000
6001 free(curproxy->conf.lfsd_file);
6002 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6003 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6004
6005 /* get a chance to improve log-format-sd error reporting by
6006 * reporting the correct line-number when possible.
6007 */
6008 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6009 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6010 file, linenum, curproxy->id);
6011 err_code |= ERR_WARN;
6012 }
6013 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006014 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6015 if (*(args[1]) == 0) {
6016 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006020 chunk_destroy(&curproxy->log_tag);
6021 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006022 }
William Lallemand0f99e342011-10-12 17:50:54 +02006023 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6024 /* delete previous herited or defined syslog servers */
6025 struct logsrv *back;
6026
6027 if (*(args[1]) != 0) {
6028 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
6032
William Lallemand723b73a2012-02-08 16:37:49 +01006033 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6034 LIST_DEL(&tmplogsrv->list);
6035 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006036 }
6037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006039 struct logsrv *logsrv;
6040
Willy Tarreaubaaee002006-06-26 02:48:02 +02006041 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006042 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006043 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006044 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006045 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006046 LIST_INIT(&node->list);
6047 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 }
6050 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006051 struct sockaddr_storage *sk;
6052 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006053 int arg = 0;
6054 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006055
Vincent Bernat02779b62016-04-03 13:48:43 +02006056 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057
Willy Tarreau18324f52014-06-27 18:10:07 +02006058 /* just after the address, a length may be specified */
6059 if (strcmp(args[arg+2], "len") == 0) {
6060 len = atoi(args[arg+3]);
6061 if (len < 80 || len > 65535) {
6062 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6063 file, linenum, args[arg+3]);
6064 err_code |= ERR_ALERT | ERR_FATAL;
6065 goto out;
6066 }
6067 logsrv->maxlen = len;
6068
6069 /* skip these two args */
6070 arg += 2;
6071 }
6072 else
6073 logsrv->maxlen = MAX_SYSLOG_LEN;
6074
6075 if (logsrv->maxlen > global.max_syslog_len) {
6076 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006077 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6078 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6079 logline = my_realloc2(logline, global.max_syslog_len + 1);
6080 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006081 }
6082
Dragan Dosen1322d092015-09-22 16:05:32 +02006083 /* after the length, a format may be specified */
6084 if (strcmp(args[arg+2], "format") == 0) {
6085 logsrv->format = get_log_format(args[arg+3]);
6086 if (logsrv->format < 0) {
6087 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
6090 }
6091
6092 /* skip these two args */
6093 arg += 2;
6094 }
6095
William Lallemanddf1425a2015-04-28 20:17:49 +02006096 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6097 goto out;
6098
Willy Tarreau18324f52014-06-27 18:10:07 +02006099 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006100 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006101 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 }
6106
William Lallemand0f99e342011-10-12 17:50:54 +02006107 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006108 if (*(args[arg+3])) {
6109 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006111 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
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 }
6117
William Lallemand0f99e342011-10-12 17:50:54 +02006118 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006119 if (*(args[arg+4])) {
6120 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006121 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006122 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006123 err_code |= ERR_ALERT | ERR_FATAL;
6124 goto out;
6125
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006126 }
6127 }
6128
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006129 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006130 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006131 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006132 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006133 goto out;
6134 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006136 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006137
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006138 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006139 if (port1 != port2) {
6140 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6141 file, linenum, args[0], args[1]);
6142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
6144 }
6145
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006147 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 }
William Lallemand0f99e342011-10-12 17:50:54 +02006149
6150 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 }
6152 else {
6153 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6154 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006155 err_code |= ERR_ALERT | ERR_FATAL;
6156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 }
6158 }
6159 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006160 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006161 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006162 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006163 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006164
Willy Tarreau977b8e42006-12-29 14:19:17 +01006165 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006166 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006167
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006169 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6170 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006171 err_code |= ERR_ALERT | ERR_FATAL;
6172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006174
6175 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006176 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6177 free(curproxy->conn_src.iface_name);
6178 curproxy->conn_src.iface_name = NULL;
6179 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006180
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006181 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006182 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006183 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006184 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006185 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006186 goto out;
6187 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006188
6189 proto = protocol_by_family(sk->ss_family);
6190 if (!proto || !proto->connect) {
6191 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006192 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006193 err_code |= ERR_ALERT | ERR_FATAL;
6194 goto out;
6195 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006196
6197 if (port1 != port2) {
6198 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6199 file, linenum, args[0], args[1]);
6200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202 }
6203
Willy Tarreauef9a3602012-12-08 22:29:20 +01006204 curproxy->conn_src.source_addr = *sk;
6205 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006206
6207 cur_arg = 2;
6208 while (*(args[cur_arg])) {
6209 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006210#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006211 if (!*args[cur_arg + 1]) {
6212 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6213 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006216 }
6217
6218 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006219 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6220 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006221 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006222 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6223 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006224 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6225 char *name, *end;
6226
6227 name = args[cur_arg+1] + 7;
6228 while (isspace(*name))
6229 name++;
6230
6231 end = name;
6232 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6233 end++;
6234
Willy Tarreauef9a3602012-12-08 22:29:20 +01006235 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6236 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6237 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6238 curproxy->conn_src.bind_hdr_len = end - name;
6239 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6240 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6241 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006242
6243 /* now look for an occurrence number */
6244 while (isspace(*end))
6245 end++;
6246 if (*end == ',') {
6247 end++;
6248 name = end;
6249 if (*end == '-')
6250 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006251 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006252 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006253 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006254 }
6255
Willy Tarreauef9a3602012-12-08 22:29:20 +01006256 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006257 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6258 " occurrences values smaller than %d.\n",
6259 file, linenum, MAX_HDR_HISTORY);
6260 err_code |= ERR_ALERT | ERR_FATAL;
6261 goto out;
6262 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006263 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006264 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006265
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006266 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006267 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006268 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006269 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006270 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006271 goto out;
6272 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006273
6274 proto = protocol_by_family(sk->ss_family);
6275 if (!proto || !proto->connect) {
6276 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6277 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
6280 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006282 if (port1 != port2) {
6283 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6284 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006285 err_code |= ERR_ALERT | ERR_FATAL;
6286 goto out;
6287 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006288 curproxy->conn_src.tproxy_addr = *sk;
6289 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006290 }
6291 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006292#else /* no TPROXY support */
6293 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006294 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006295 err_code |= ERR_ALERT | ERR_FATAL;
6296 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006297#endif
6298 cur_arg += 2;
6299 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006300 }
6301
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6303#ifdef SO_BINDTODEVICE
6304 if (!*args[cur_arg + 1]) {
6305 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006309 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006310 free(curproxy->conn_src.iface_name);
6311 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6312 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006313 global.last_checks |= LSTCHK_NETADM;
6314#else
6315 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6316 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006317 err_code |= ERR_ALERT | ERR_FATAL;
6318 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006319#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006320 cur_arg += 2;
6321 continue;
6322 }
6323 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006324 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006329 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6330 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6331 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006332 err_code |= ERR_ALERT | ERR_FATAL;
6333 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006339 err_code |= ERR_ALERT | ERR_FATAL;
6340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342
6343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006344 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006345 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006351 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006365 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 }
6370 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006372 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006373 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006377 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006379 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006380 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006382 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6387 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006391
6392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006393 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006394 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 }
6398 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006400 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006401 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006407 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006408 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
6412 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006414 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006415 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
6419 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006421 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006422 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006426 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006428 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006429 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006431 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006434 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006435
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 if (curproxy == &defproxy) {
6437 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006438 err_code |= ERR_ALERT | ERR_FATAL;
6439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006441 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006442 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 if (*(args[1]) == 0) {
6445 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006449
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006450 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006451 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6452 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6453 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006454 err_code |= ERR_ALERT | ERR_FATAL;
6455 goto out;
6456 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006457 err_code |= warnif_cond_conflicts(cond,
6458 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6459 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006460 }
6461 else if (*args[2]) {
6462 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6463 file, linenum, args[0], args[2]);
6464 err_code |= ERR_ALERT | ERR_FATAL;
6465 goto out;
6466 }
6467
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006468 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006469 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006470 wl->s = strdup(args[1]);
6471 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006472 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 }
6474 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006478 err_code |= ERR_ALERT | ERR_FATAL;
6479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006481
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006483 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006484 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 }
6488 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006490 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006491 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 }
6495 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006497 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006498 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006511 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006512 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 }
6516 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006518 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006519 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 }
6523 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006525 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006526 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006527 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 }
6530 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006531 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006532
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 if (curproxy == &defproxy) {
6534 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006535 err_code |= ERR_ALERT | ERR_FATAL;
6536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006538 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006539 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 if (*(args[1]) == 0) {
6542 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_ALERT | ERR_FATAL;
6544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 }
6546
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006547 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006548 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6549 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6550 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006551 err_code |= ERR_ALERT | ERR_FATAL;
6552 goto out;
6553 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006554 err_code |= warnif_cond_conflicts(cond,
6555 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6556 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006557 }
6558 else if (*args[2]) {
6559 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6560 file, linenum, args[0], args[2]);
6561 err_code |= ERR_ALERT | ERR_FATAL;
6562 goto out;
6563 }
6564
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006565 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006566 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006567 wl->s = strdup(args[1]);
6568 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569 }
6570 else if (!strcmp(args[0], "errorloc") ||
6571 !strcmp(args[0], "errorloc302") ||
6572 !strcmp(args[0], "errorloc303")) { /* error location */
6573 int errnum, errlen;
6574 char *err;
6575
Willy Tarreau977b8e42006-12-29 14:19:17 +01006576 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006577 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006578
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006580 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006581 err_code |= ERR_ALERT | ERR_FATAL;
6582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 }
6584
6585 errnum = atol(args[1]);
6586 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006587 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6588 err = malloc(errlen);
6589 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006591 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6592 err = malloc(errlen);
6593 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 }
6595
Willy Tarreau0f772532006-12-23 20:51:41 +01006596 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6597 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006598 chunk_destroy(&curproxy->errmsg[rc]);
6599 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006600 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006603
6604 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006605 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6606 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607 free(err);
6608 }
6609 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006610 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6611 int errnum, errlen, fd;
6612 char *err;
6613 struct stat stat;
6614
6615 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006616 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006617
6618 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006619 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006620 err_code |= ERR_ALERT | ERR_FATAL;
6621 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006622 }
6623
6624 fd = open(args[2], O_RDONLY);
6625 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6626 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6627 file, linenum, args[2], args[1]);
6628 if (fd >= 0)
6629 close(fd);
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
Willy Tarreau27a674e2009-08-17 07:23:33 +02006634 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006635 errlen = stat.st_size;
6636 } else {
6637 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006638 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006639 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006640 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006641 }
6642
6643 err = malloc(errlen); /* malloc() must succeed during parsing */
6644 errnum = read(fd, err, errlen);
6645 if (errnum != errlen) {
6646 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6647 file, linenum, args[2], args[1]);
6648 close(fd);
6649 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006650 err_code |= ERR_ALERT | ERR_FATAL;
6651 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006652 }
6653 close(fd);
6654
6655 errnum = atol(args[1]);
6656 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6657 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006658 chunk_destroy(&curproxy->errmsg[rc]);
6659 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006660 break;
6661 }
6662 }
6663
6664 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006665 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6666 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006667 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006668 free(err);
6669 }
6670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006672 struct cfg_kw_list *kwl;
6673 int index;
6674
6675 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6676 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6677 if (kwl->kw[index].section != CFG_LISTEN)
6678 continue;
6679 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6680 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006681 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006682 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006683 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006686 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006687 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006688 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006689 err_code |= ERR_WARN;
6690 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006691 }
Willy Tarreau93893792009-07-23 13:19:11 +02006692 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006693 }
6694 }
6695 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006696
Willy Tarreau6daf3432008-01-22 16:44:08 +01006697 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006698 err_code |= ERR_ALERT | ERR_FATAL;
6699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006700 }
Willy Tarreau93893792009-07-23 13:19:11 +02006701 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006702 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006703 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006704}
6705
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006706int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006707cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6708{
6709#ifdef CONFIG_HAP_NS
6710 const char *err;
6711 const char *item = args[0];
6712
6713 if (!strcmp(item, "namespace_list")) {
6714 return 0;
6715 }
6716 else if (!strcmp(item, "namespace")) {
6717 size_t idx = 1;
6718 const char *current;
6719 while (*(current = args[idx++])) {
6720 err = invalid_char(current);
6721 if (err) {
6722 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6723 file, linenum, *err, item, current);
6724 return ERR_ALERT | ERR_FATAL;
6725 }
6726
6727 if (netns_store_lookup(current, strlen(current))) {
6728 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6729 file, linenum, current);
6730 return ERR_ALERT | ERR_FATAL;
6731 }
6732 if (!netns_store_insert(current)) {
6733 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6734 file, linenum, current);
6735 return ERR_ALERT | ERR_FATAL;
6736 }
6737 }
6738 }
6739
6740 return 0;
6741#else
6742 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6743 file, linenum);
6744 return ERR_ALERT | ERR_FATAL;
6745#endif
6746}
6747
6748int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006749cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6750{
6751
6752 int err_code = 0;
6753 const char *err;
6754
6755 if (!strcmp(args[0], "userlist")) { /* new userlist */
6756 struct userlist *newul;
6757
6758 if (!*args[1]) {
6759 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6760 file, linenum, args[0]);
6761 err_code |= ERR_ALERT | ERR_FATAL;
6762 goto out;
6763 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006764 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6765 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766
6767 err = invalid_char(args[1]);
6768 if (err) {
6769 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6770 file, linenum, *err, args[0], args[1]);
6771 err_code |= ERR_ALERT | ERR_FATAL;
6772 goto out;
6773 }
6774
6775 for (newul = userlist; newul; newul = newul->next)
6776 if (!strcmp(newul->name, args[1])) {
6777 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6778 file, linenum, args[1]);
6779 err_code |= ERR_WARN;
6780 goto out;
6781 }
6782
Vincent Bernat02779b62016-04-03 13:48:43 +02006783 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006784 if (!newul) {
6785 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6786 err_code |= ERR_ALERT | ERR_ABORT;
6787 goto out;
6788 }
6789
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006790 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006791 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6793 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006794 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 goto out;
6796 }
6797
6798 newul->next = userlist;
6799 userlist = newul;
6800
6801 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006802 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006804 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805
6806 if (!*args[1]) {
6807 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6808 file, linenum, args[0]);
6809 err_code |= ERR_ALERT | ERR_FATAL;
6810 goto out;
6811 }
6812
6813 err = invalid_char(args[1]);
6814 if (err) {
6815 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6816 file, linenum, *err, args[0], args[1]);
6817 err_code |= ERR_ALERT | ERR_FATAL;
6818 goto out;
6819 }
6820
William Lallemand4ac9f542015-05-28 18:03:51 +02006821 if (!userlist)
6822 goto out;
6823
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006824 for (ag = userlist->groups; ag; ag = ag->next)
6825 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006826 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6827 file, linenum, args[1], userlist->name);
6828 err_code |= ERR_ALERT;
6829 goto out;
6830 }
6831
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006832 ag = calloc(1, sizeof(*ag));
6833 if (!ag) {
6834 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6835 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006836 goto out;
6837 }
6838
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006839 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006840 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006841 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6842 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006843 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006844 goto out;
6845 }
6846
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006847 cur_arg = 2;
6848
6849 while (*args[cur_arg]) {
6850 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 cur_arg += 2;
6853 continue;
6854 } else {
6855 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6856 file, linenum, args[0]);
6857 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006858 free(ag->groupusers);
6859 free(ag->name);
6860 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006861 goto out;
6862 }
6863 }
6864
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006865 ag->next = userlist->groups;
6866 userlist->groups = ag;
6867
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 } else if (!strcmp(args[0], "user")) { /* new user */
6869 struct auth_users *newuser;
6870 int cur_arg;
6871
6872 if (!*args[1]) {
6873 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6874 file, linenum, args[0]);
6875 err_code |= ERR_ALERT | ERR_FATAL;
6876 goto out;
6877 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006878 if (!userlist)
6879 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006880
6881 for (newuser = userlist->users; newuser; newuser = newuser->next)
6882 if (!strcmp(newuser->user, args[1])) {
6883 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6884 file, linenum, args[1], userlist->name);
6885 err_code |= ERR_ALERT;
6886 goto out;
6887 }
6888
Vincent Bernat02779b62016-04-03 13:48:43 +02006889 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006890 if (!newuser) {
6891 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6892 err_code |= ERR_ALERT | ERR_ABORT;
6893 goto out;
6894 }
6895
6896 newuser->user = strdup(args[1]);
6897
6898 newuser->next = userlist->users;
6899 userlist->users = newuser;
6900
6901 cur_arg = 2;
6902
6903 while (*args[cur_arg]) {
6904 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006905#ifdef CONFIG_HAP_CRYPT
6906 if (!crypt("", args[cur_arg + 1])) {
6907 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6908 file, linenum, newuser->user);
6909 err_code |= ERR_ALERT | ERR_FATAL;
6910 goto out;
6911 }
6912#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006913 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6914 file, linenum);
6915 err_code |= ERR_ALERT;
6916#endif
6917 newuser->pass = strdup(args[cur_arg + 1]);
6918 cur_arg += 2;
6919 continue;
6920 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6921 newuser->pass = strdup(args[cur_arg + 1]);
6922 newuser->flags |= AU_O_INSECURE;
6923 cur_arg += 2;
6924 continue;
6925 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006926 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006927 cur_arg += 2;
6928 continue;
6929 } else {
6930 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6931 file, linenum, args[0]);
6932 err_code |= ERR_ALERT | ERR_FATAL;
6933 goto out;
6934 }
6935 }
6936 } else {
6937 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6938 err_code |= ERR_ALERT | ERR_FATAL;
6939 }
6940
6941out:
6942 return err_code;
6943}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944
Christopher Faulet79bdef32016-11-04 22:36:15 +01006945int
6946cfg_parse_scope(const char *file, int linenum, char *line)
6947{
6948 char *beg, *end, *scope = NULL;
6949 int err_code = 0;
6950 const char *err;
6951
6952 beg = line + 1;
6953 end = strchr(beg, ']');
6954
6955 /* Detect end of scope declaration */
6956 if (!end || end == beg) {
6957 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6958 file, linenum);
6959 err_code |= ERR_ALERT | ERR_FATAL;
6960 goto out;
6961 }
6962
6963 /* Get scope name and check its validity */
6964 scope = my_strndup(beg, end-beg);
6965 err = invalid_char(scope);
6966 if (err) {
6967 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6968 file, linenum, *err);
6969 err_code |= ERR_ALERT | ERR_ABORT;
6970 goto out;
6971 }
6972
6973 /* Be sure to have a scope declaration alone on its line */
6974 line = end+1;
6975 while (isspace((unsigned char)*line))
6976 line++;
6977 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6978 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6979 file, linenum, *line);
6980 err_code |= ERR_ALERT | ERR_ABORT;
6981 goto out;
6982 }
6983
6984 /* We have a valid scope declaration, save it */
6985 free(cfg_scope);
6986 cfg_scope = scope;
6987 scope = NULL;
6988
6989 out:
6990 free(scope);
6991 return err_code;
6992}
6993
Willy Tarreaubaaee002006-06-26 02:48:02 +02006994/*
6995 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006996 * Returns the error code, 0 if OK, or any combination of :
6997 * - ERR_ABORT: must abort ASAP
6998 * - ERR_FATAL: we can continue parsing but not start the service
6999 * - ERR_WARN: a warning has been emitted
7000 * - ERR_ALERT: an alert has been emitted
7001 * Only the two first ones can stop processing, the two others are just
7002 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007004int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005{
William Lallemand64e84512015-05-12 14:25:37 +02007006 char *thisline;
7007 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 FILE *f;
7009 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007010 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007011 struct cfg_section *cs = NULL;
7012 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007013 int readbytes = 0;
7014
7015 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007016 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007017 return -1;
7018 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007019
David Carlier97880bb2016-04-08 10:35:26 +01007020 if ((f=fopen(file,"r")) == NULL) {
7021 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007022 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024
William Lallemandb2f07452015-05-12 14:27:13 +02007025next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007026 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007027 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007028 char *end;
7029 char *args[MAX_LINE_ARGS + 1];
7030 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007031 int dquote = 0; /* double quote */
7032 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007033
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 linenum++;
7035
7036 end = line + strlen(line);
7037
William Lallemand64e84512015-05-12 14:25:37 +02007038 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007039 /* Check if we reached the limit and the last char is not \n.
7040 * Watch out for the last line without the terminating '\n'!
7041 */
William Lallemand64e84512015-05-12 14:25:37 +02007042 char *newline;
7043 int newlinesize = linesize * 2;
7044
7045 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7046 if (newline == NULL) {
7047 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7048 file, linenum);
7049 err_code |= ERR_ALERT | ERR_FATAL;
7050 continue;
7051 }
7052
7053 readbytes = linesize - 1;
7054 linesize = newlinesize;
7055 thisline = newline;
7056 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007057 }
7058
William Lallemand64e84512015-05-12 14:25:37 +02007059 readbytes = 0;
7060
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007062 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007063 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007064
Christopher Faulet79bdef32016-11-04 22:36:15 +01007065
7066 if (*line == '[') {/* This is the begining if a scope */
7067 err_code |= cfg_parse_scope(file, linenum, line);
7068 goto next_line;
7069 }
7070
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071 arg = 0;
7072 args[arg] = line;
7073
7074 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007075 if (*line == '"' && !squote) { /* double quote outside single quotes */
7076 if (dquote)
7077 dquote = 0;
7078 else
7079 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007080 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007081 end--;
7082 }
7083 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7084 if (squote)
7085 squote = 0;
7086 else
7087 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007088 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007089 end--;
7090 }
7091 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007092 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7093 * C equivalent value. Other combinations left unchanged (eg: \1).
7094 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 int skip = 0;
7096 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7097 *line = line[1];
7098 skip = 1;
7099 }
7100 else if (line[1] == 'r') {
7101 *line = '\r';
7102 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 else if (line[1] == 'n') {
7105 *line = '\n';
7106 skip = 1;
7107 }
7108 else if (line[1] == 't') {
7109 *line = '\t';
7110 skip = 1;
7111 }
7112 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007113 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 unsigned char hex1, hex2;
7115 hex1 = toupper(line[2]) - '0';
7116 hex2 = toupper(line[3]) - '0';
7117 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7118 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7119 *line = (hex1<<4) + hex2;
7120 skip = 3;
7121 }
7122 else {
7123 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007125 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007126 } else if (line[1] == '"') {
7127 *line = '"';
7128 skip = 1;
7129 } else if (line[1] == '\'') {
7130 *line = '\'';
7131 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007132 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7133 *line = '$';
7134 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007135 }
7136 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007137 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007138 end -= skip;
7139 }
7140 line++;
7141 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007142 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 /* end of string, end of loop */
7144 *line = 0;
7145 break;
7146 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007147 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007148 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007149 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007150 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151 line++;
7152 args[++arg] = line;
7153 }
William Lallemandb2f07452015-05-12 14:27:13 +02007154 else if (dquote && *line == '$') {
7155 /* environment variables are evaluated inside double quotes */
7156 char *var_beg;
7157 char *var_end;
7158 char save_char;
7159 char *value;
7160 int val_len;
7161 int newlinesize;
7162 int braces = 0;
7163
7164 var_beg = line + 1;
7165 var_end = var_beg;
7166
7167 if (*var_beg == '{') {
7168 var_beg++;
7169 var_end++;
7170 braces = 1;
7171 }
7172
7173 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7174 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7175 err_code |= ERR_ALERT | ERR_FATAL;
7176 goto next_line; /* skip current line */
7177 }
7178
7179 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7180 var_end++;
7181
7182 save_char = *var_end;
7183 *var_end = '\0';
7184 value = getenv(var_beg);
7185 *var_end = save_char;
7186 val_len = value ? strlen(value) : 0;
7187
7188 if (braces) {
7189 if (*var_end == '}') {
7190 var_end++;
7191 braces = 0;
7192 } else {
7193 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7194 err_code |= ERR_ALERT | ERR_FATAL;
7195 goto next_line; /* skip current line */
7196 }
7197 }
7198
7199 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7200
7201 /* if not enough space in thisline */
7202 if (newlinesize > linesize) {
7203 char *newline;
7204
7205 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7206 if (newline == NULL) {
7207 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7208 err_code |= ERR_ALERT | ERR_FATAL;
7209 goto next_line; /* slip current line */
7210 }
7211 /* recompute pointers if realloc returns a new pointer */
7212 if (newline != thisline) {
7213 int i;
7214 int diff;
7215
7216 for (i = 0; i <= arg; i++) {
7217 diff = args[i] - thisline;
7218 args[i] = newline + diff;
7219 }
7220
7221 diff = var_end - thisline;
7222 var_end = newline + diff;
7223 diff = end - thisline;
7224 end = newline + diff;
7225 diff = line - thisline;
7226 line = newline + diff;
7227 thisline = newline;
7228 }
7229 linesize = newlinesize;
7230 }
7231
7232 /* insert value inside the line */
7233 memmove(line + val_len, var_end, end - var_end + 1);
7234 memcpy(line, value, val_len);
7235 end += val_len - (var_end - line);
7236 line += val_len;
7237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007238 else {
7239 line++;
7240 }
7241 }
William Lallemandb2f07452015-05-12 14:27:13 +02007242
William Lallemandf9873ba2015-05-05 17:37:14 +02007243 if (dquote) {
7244 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7245 err_code |= ERR_ALERT | ERR_FATAL;
7246 }
7247
7248 if (squote) {
7249 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7250 err_code |= ERR_ALERT | ERR_FATAL;
7251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007252
7253 /* empty line */
7254 if (!**args)
7255 continue;
7256
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007257 if (*line) {
7258 /* we had to stop due to too many args.
7259 * Let's terminate the string, print the offending part then cut the
7260 * last arg.
7261 */
7262 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7263 line++;
7264 *line = '\0';
7265
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007266 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007267 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007268 err_code |= ERR_ALERT | ERR_FATAL;
7269 args[arg] = line;
7270 }
7271
Willy Tarreau540abe42007-05-02 20:50:16 +02007272 /* zero out remaining args and ensure that at least one entry
7273 * is zeroed out.
7274 */
7275 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007276 args[arg] = line;
7277 }
7278
Willy Tarreau3842f002009-06-14 11:39:52 +02007279 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007280 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007281 char *tmp;
7282
Willy Tarreau3842f002009-06-14 11:39:52 +02007283 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007284 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007285 for (arg=0; *args[arg+1]; arg++)
7286 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007287 *tmp = '\0'; // fix the next arg to \0
7288 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007289 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007290 else if (!strcmp(args[0], "default")) {
7291 kwm = KWM_DEF;
7292 for (arg=0; *args[arg+1]; arg++)
7293 args[arg] = args[arg+1]; // shift args after inversion
7294 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007295
William Lallemand0f99e342011-10-12 17:50:54 +02007296 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7297 strcmp(args[0], "log") != 0) {
7298 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007299 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007300 }
7301
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007302 /* detect section start */
7303 list_for_each_entry(ics, &sections, list) {
7304 if (strcmp(args[0], ics->section_name) == 0) {
7305 cursection = ics->section_name;
7306 cs = ics;
7307 break;
7308 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007309 }
7310
Willy Tarreaubaaee002006-06-26 02:48:02 +02007311 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007312 if (cs)
7313 err_code |= cs->section_parser(file, linenum, args, kwm);
7314 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007315 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007316 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007317 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007318
7319 if (err_code & ERR_ABORT)
7320 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007321 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007322 free(cfg_scope);
7323 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007324 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007325 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007326 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007327 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007328}
7329
Willy Tarreau64ab6072014-09-16 12:17:36 +02007330/* This function propagates processes from frontend <from> to backend <to> so
7331 * that it is always guaranteed that a backend pointed to by a frontend is
7332 * bound to all of its processes. After that, if the target is a "listen"
7333 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007334 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007335 * checked first to ensure that <to> is already bound to all processes of
7336 * <from>, there is no risk of looping and we ensure to follow the shortest
7337 * path to the destination.
7338 *
7339 * It is possible to set <to> to NULL for the first call so that the function
7340 * takes care of visiting the initial frontend in <from>.
7341 *
7342 * It is important to note that the function relies on the fact that all names
7343 * have already been resolved.
7344 */
7345void propagate_processes(struct proxy *from, struct proxy *to)
7346{
7347 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007348
7349 if (to) {
7350 /* check whether we need to go down */
7351 if (from->bind_proc &&
7352 (from->bind_proc & to->bind_proc) == from->bind_proc)
7353 return;
7354
7355 if (!from->bind_proc && !to->bind_proc)
7356 return;
7357
7358 to->bind_proc = from->bind_proc ?
7359 (to->bind_proc | from->bind_proc) : 0;
7360
7361 /* now propagate down */
7362 from = to;
7363 }
7364
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007365 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007366 return;
7367
Willy Tarreauf6b70012014-12-18 14:00:43 +01007368 if (from->state == PR_STSTOPPED)
7369 return;
7370
Willy Tarreau64ab6072014-09-16 12:17:36 +02007371 /* default_backend */
7372 if (from->defbe.be)
7373 propagate_processes(from, from->defbe.be);
7374
7375 /* use_backend */
7376 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007377 if (rule->dynamic)
7378 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007379 to = rule->be.backend;
7380 propagate_processes(from, to);
7381 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007382}
7383
Willy Tarreaubb925012009-07-23 13:36:36 +02007384/*
7385 * Returns the error code, 0 if OK, or any combination of :
7386 * - ERR_ABORT: must abort ASAP
7387 * - ERR_FATAL: we can continue parsing but not start the service
7388 * - ERR_WARN: a warning has been emitted
7389 * - ERR_ALERT: an alert has been emitted
7390 * Only the two first ones can stop processing, the two others are just
7391 * indicators.
7392 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007393int check_config_validity()
7394{
7395 int cfgerr = 0;
7396 struct proxy *curproxy = NULL;
7397 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007398 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007399 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007400 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007401 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007402 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007404 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007405 /*
7406 * Now, check for the integrity of all that we have collected.
7407 */
7408
7409 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007410 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007411
Willy Tarreau193b8c62012-11-22 00:17:38 +01007412 if (!global.tune.max_http_hdr)
7413 global.tune.max_http_hdr = MAX_HTTP_HDR;
7414
7415 if (!global.tune.cookie_len)
7416 global.tune.cookie_len = CAPTURE_LEN;
7417
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007418 if (!global.tune.requri_len)
7419 global.tune.requri_len = REQURI_LEN;
7420
Emeric Brun96fd9262017-07-05 13:33:16 +02007421 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7422
Willy Tarreau193b8c62012-11-22 00:17:38 +01007423 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7424
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007425 /* allocate pool of resolution per resolvers */
7426 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7427 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7428 /* error message is already displayed by dns_alloc_resolution_pool() */
7429 err_code |= ERR_ALERT | ERR_ABORT;
7430 goto out;
7431 }
7432 }
7433
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007434 /* Post initialisation of the users and groups lists. */
7435 err_code = userlist_postinit();
7436 if (err_code != ERR_NONE)
7437 goto out;
7438
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007439 /* first, we will invert the proxy list order */
7440 curproxy = NULL;
7441 while (proxy) {
7442 struct proxy *next;
7443
7444 next = proxy->next;
7445 proxy->next = curproxy;
7446 curproxy = proxy;
7447 if (!next)
7448 break;
7449 proxy = next;
7450 }
7451
Willy Tarreau419ead82014-09-16 13:41:21 +02007452 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007453 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007454 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007455 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007456 struct act_rule *trule;
7457 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007458 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007459 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007460 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007461
Willy Tarreau050536d2012-10-04 08:47:34 +02007462 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007463 /* proxy ID not set, use automatic numbering with first
7464 * spare entry starting with next_pxid.
7465 */
7466 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7467 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7468 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007469 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007470 next_pxid++;
7471
Willy Tarreau55ea7572007-06-17 19:56:27 +02007472
Willy Tarreaubaaee002006-06-26 02:48:02 +02007473 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007474 /* ensure we don't keep listeners uselessly bound */
7475 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007476 free((void *)curproxy->table.peers.name);
7477 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007478 continue;
7479 }
7480
Willy Tarreau102df612014-05-07 23:56:38 +02007481 /* Check multi-process mode compatibility for the current proxy */
7482
7483 if (curproxy->bind_proc) {
7484 /* an explicit bind-process was specified, let's check how many
7485 * processes remain.
7486 */
David Carliere6c39412015-07-02 07:00:17 +00007487 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007488
7489 curproxy->bind_proc &= nbits(global.nbproc);
7490 if (!curproxy->bind_proc && nbproc == 1) {
7491 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);
7492 curproxy->bind_proc = 1;
7493 }
7494 else if (!curproxy->bind_proc && nbproc > 1) {
7495 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);
7496 curproxy->bind_proc = 0;
7497 }
7498 }
7499
Willy Tarreau3d209582014-05-09 17:06:11 +02007500 /* check and reduce the bind-proc of each listener */
7501 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7502 unsigned long mask;
7503
7504 if (!bind_conf->bind_proc)
7505 continue;
7506
7507 mask = nbits(global.nbproc);
7508 if (curproxy->bind_proc)
7509 mask &= curproxy->bind_proc;
7510 /* mask cannot be null here thanks to the previous checks */
7511
David Carliere6c39412015-07-02 07:00:17 +00007512 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007513 bind_conf->bind_proc &= mask;
7514
7515 if (!bind_conf->bind_proc && nbproc == 1) {
7516 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",
7517 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7518 bind_conf->bind_proc = mask & ~(mask - 1);
7519 }
7520 else if (!bind_conf->bind_proc && nbproc > 1) {
7521 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",
7522 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7523 bind_conf->bind_proc = 0;
7524 }
7525 }
7526
Willy Tarreauff01a212009-03-15 13:46:16 +01007527 switch (curproxy->mode) {
7528 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007529 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007530 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007531 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7532 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007533 cfgerr++;
7534 }
7535
7536 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 Warning("config : servers will be ignored for %s '%s'.\n",
7538 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007539 break;
7540
7541 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007542 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007543 break;
7544
7545 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007546 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007547 break;
7548 }
7549
Willy Tarreauf3934b82015-08-11 11:36:45 +02007550 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7551 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7552 proxy_type_str(curproxy), curproxy->id);
7553 err_code |= ERR_WARN;
7554 }
7555
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007556 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007557 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007558 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007559 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7560 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007561 cfgerr++;
7562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007563#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007564 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007565 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7566 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007567 cfgerr++;
7568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007569#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007570 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007571 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7572 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007573 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007574 }
7575 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007576 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007577 /* If no LB algo is set in a backend, and we're not in
7578 * transparent mode, dispatch mode nor proxy mode, we
7579 * want to use balance roundrobin by default.
7580 */
7581 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7582 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007583 }
7584 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007585
Willy Tarreau1620ec32011-08-06 17:05:02 +02007586 if (curproxy->options & PR_O_DISPATCH)
7587 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7588 else if (curproxy->options & PR_O_HTTP_PROXY)
7589 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7590 else if (curproxy->options & PR_O_TRANSP)
7591 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007592
Willy Tarreau1620ec32011-08-06 17:05:02 +02007593 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7594 if (curproxy->options & PR_O_DISABLE404) {
7595 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7596 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7597 err_code |= ERR_WARN;
7598 curproxy->options &= ~PR_O_DISABLE404;
7599 }
7600 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7601 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7602 "send-state", proxy_type_str(curproxy), curproxy->id);
7603 err_code |= ERR_WARN;
7604 curproxy->options &= ~PR_O2_CHK_SNDST;
7605 }
Willy Tarreauef781042010-01-27 11:53:01 +01007606 }
7607
Simon Horman98637e52014-06-20 12:30:16 +09007608 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7609 if (!global.external_check) {
7610 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7611 curproxy->id, "option external-check");
7612 cfgerr++;
7613 }
7614 if (!curproxy->check_command) {
7615 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7616 curproxy->id, "option external-check");
7617 cfgerr++;
7618 }
7619 }
7620
Simon Horman64e34162015-02-06 11:11:57 +09007621 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007622 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7623 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007624 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7625 "'email-alert myhostname', or 'email-alert to' "
7626 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007627 "to be present).\n",
7628 proxy_type_str(curproxy), curproxy->id);
7629 err_code |= ERR_WARN;
7630 free_email_alert(curproxy);
7631 }
7632 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007633 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007634 }
7635
Simon Horman98637e52014-06-20 12:30:16 +09007636 if (curproxy->check_command) {
7637 int clear = 0;
7638 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7639 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7640 "external-check command", proxy_type_str(curproxy), curproxy->id);
7641 err_code |= ERR_WARN;
7642 clear = 1;
7643 }
7644 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007645 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007646 curproxy->id, "external-check command");
7647 cfgerr++;
7648 }
7649 if (clear) {
7650 free(curproxy->check_command);
7651 curproxy->check_command = NULL;
7652 }
7653 }
7654
7655 if (curproxy->check_path) {
7656 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7657 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7658 "external-check path", proxy_type_str(curproxy), curproxy->id);
7659 err_code |= ERR_WARN;
7660 free(curproxy->check_path);
7661 curproxy->check_path = NULL;
7662 }
7663 }
7664
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007665 /* if a default backend was specified, let's find it */
7666 if (curproxy->defbe.name) {
7667 struct proxy *target;
7668
Willy Tarreauafb39922015-05-26 12:04:09 +02007669 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007670 if (!target) {
7671 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7672 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007673 cfgerr++;
7674 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007675 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7676 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007677 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007678 } else if (target->mode != curproxy->mode &&
7679 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7680
7681 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7682 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7683 curproxy->conf.file, curproxy->conf.line,
7684 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7685 target->conf.file, target->conf.line);
7686 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007687 } else {
7688 free(curproxy->defbe.name);
7689 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007690 /* Update tot_fe_maxconn for a further fullconn's computation */
7691 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007692 /* Emit a warning if this proxy also has some servers */
7693 if (curproxy->srv) {
7694 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7695 curproxy->id);
7696 err_code |= ERR_WARN;
7697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007698 }
7699 }
7700
Emeric Brun3f783572017-01-12 11:21:28 +01007701 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7702 /* Case of listen without default backend
7703 * The curproxy will be its own default backend
7704 * so we update tot_fe_maxconn for a further
7705 * fullconn's computation */
7706 curproxy->tot_fe_maxconn += curproxy->maxconn;
7707 }
7708
Willy Tarreau55ea7572007-06-17 19:56:27 +02007709 /* find the target proxy for 'use_backend' rules */
7710 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007711 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007712 struct logformat_node *node;
7713 char *pxname;
7714
7715 /* Try to parse the string as a log format expression. If the result
7716 * of the parsing is only one entry containing a simple string, then
7717 * it's a standard string corresponding to a static rule, thus the
7718 * parsing is cancelled and be.name is restored to be resolved.
7719 */
7720 pxname = rule->be.name;
7721 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007722 curproxy->conf.args.ctx = ARGC_UBK;
7723 curproxy->conf.args.file = rule->file;
7724 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007725 err = NULL;
7726 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7727 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7728 rule->file, rule->line, pxname, err);
7729 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007730 cfgerr++;
7731 continue;
7732 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007733 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7734
7735 if (!LIST_ISEMPTY(&rule->be.expr)) {
7736 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7737 rule->dynamic = 1;
7738 free(pxname);
7739 continue;
7740 }
7741 /* simple string: free the expression and fall back to static rule */
7742 free(node->arg);
7743 free(node);
7744 }
7745
7746 rule->dynamic = 0;
7747 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007748
Willy Tarreauafb39922015-05-26 12:04:09 +02007749 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007750 if (!target) {
7751 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7752 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007753 cfgerr++;
7754 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007755 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7756 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007757 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007758 } else if (target->mode != curproxy->mode &&
7759 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7760
7761 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7762 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7763 curproxy->conf.file, curproxy->conf.line,
7764 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7765 target->conf.file, target->conf.line);
7766 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007767 } else {
7768 free((void *)rule->be.name);
7769 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007770 /* For each target of switching rules, we update
7771 * their tot_fe_maxconn, except if a previous rule point
7772 * on the same backend or on the default backend */
7773 if (rule->be.backend != curproxy->defbe.be) {
7774 struct switching_rule *swrule;
7775
7776 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7777 if (rule == swrule) {
7778 target->tot_fe_maxconn += curproxy->maxconn;
7779 break;
7780 }
7781 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7782 /* there is multiple ref of this backend */
7783 break;
7784 }
7785 }
7786 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007787 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007788 }
7789
Willy Tarreau64ab6072014-09-16 12:17:36 +02007790 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007791 list_for_each_entry(srule, &curproxy->server_rules, list) {
7792 struct server *target = findserver(curproxy, srule->srv.name);
7793
7794 if (!target) {
7795 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7796 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7797 cfgerr++;
7798 continue;
7799 }
7800 free((void *)srule->srv.name);
7801 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007802 }
7803
Emeric Brunb982a3d2010-01-04 15:45:53 +01007804 /* find the target table for 'stick' rules */
7805 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7806 struct proxy *target;
7807
Emeric Brun1d33b292010-01-04 15:47:17 +01007808 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7809 if (mrule->flags & STK_IS_STORE)
7810 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7811
Emeric Brunb982a3d2010-01-04 15:45:53 +01007812 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007813 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007814 else
7815 target = curproxy;
7816
7817 if (!target) {
7818 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7819 curproxy->id, mrule->table.name);
7820 cfgerr++;
7821 }
7822 else if (target->table.size == 0) {
7823 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7824 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7825 cfgerr++;
7826 }
Willy Tarreau12785782012-04-27 21:37:17 +02007827 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7828 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007829 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7830 cfgerr++;
7831 }
7832 else {
7833 free((void *)mrule->table.name);
7834 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007835 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007836 }
7837 }
7838
7839 /* find the target table for 'store response' rules */
7840 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7841 struct proxy *target;
7842
Emeric Brun1d33b292010-01-04 15:47:17 +01007843 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7844
Emeric Brunb982a3d2010-01-04 15:45:53 +01007845 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007846 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007847 else
7848 target = curproxy;
7849
7850 if (!target) {
7851 Alert("Proxy '%s': unable to find store table '%s'.\n",
7852 curproxy->id, mrule->table.name);
7853 cfgerr++;
7854 }
7855 else if (target->table.size == 0) {
7856 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7857 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7858 cfgerr++;
7859 }
Willy Tarreau12785782012-04-27 21:37:17 +02007860 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7861 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007862 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7863 cfgerr++;
7864 }
7865 else {
7866 free((void *)mrule->table.name);
7867 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007868 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007869 }
7870 }
7871
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007872 /* find the target table for 'tcp-request' layer 4 rules */
7873 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7874 struct proxy *target;
7875
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007876 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007877 continue;
7878
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007879 if (trule->arg.trk_ctr.table.n)
7880 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007881 else
7882 target = curproxy;
7883
7884 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007885 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007886 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007887 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007888 cfgerr++;
7889 }
7890 else if (target->table.size == 0) {
7891 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007893 cfgerr++;
7894 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007895 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007896 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007898 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007899 cfgerr++;
7900 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007901 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007902 free(trule->arg.trk_ctr.table.n);
7903 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007904 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007905 * to pass a list of counters to track and allocate them right here using
7906 * stktable_alloc_data_type().
7907 */
7908 }
7909 }
7910
Willy Tarreau620408f2016-10-21 16:37:51 +02007911 /* find the target table for 'tcp-request' layer 5 rules */
7912 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7913 struct proxy *target;
7914
7915 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7916 continue;
7917
7918 if (trule->arg.trk_ctr.table.n)
7919 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7920 else
7921 target = curproxy;
7922
7923 if (!target) {
7924 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7925 curproxy->id, trule->arg.trk_ctr.table.n,
7926 tcp_trk_idx(trule->action));
7927 cfgerr++;
7928 }
7929 else if (target->table.size == 0) {
7930 Alert("Proxy '%s': table '%s' used but not configured.\n",
7931 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7932 cfgerr++;
7933 }
7934 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7935 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7936 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7937 tcp_trk_idx(trule->action));
7938 cfgerr++;
7939 }
7940 else {
7941 free(trule->arg.trk_ctr.table.n);
7942 trule->arg.trk_ctr.table.t = &target->table;
7943 /* Note: if we decide to enhance the track-sc syntax, we may be able
7944 * to pass a list of counters to track and allocate them right here using
7945 * stktable_alloc_data_type().
7946 */
7947 }
7948 }
7949
Willy Tarreaud1f96522010-08-03 19:34:32 +02007950 /* find the target table for 'tcp-request' layer 6 rules */
7951 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7952 struct proxy *target;
7953
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007954 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007955 continue;
7956
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007957 if (trule->arg.trk_ctr.table.n)
7958 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007959 else
7960 target = curproxy;
7961
7962 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007963 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007964 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007965 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007966 cfgerr++;
7967 }
7968 else if (target->table.size == 0) {
7969 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007970 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007971 cfgerr++;
7972 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007973 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007974 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007975 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007976 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007977 cfgerr++;
7978 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007979 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007980 free(trule->arg.trk_ctr.table.n);
7981 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007982 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007983 * to pass a list of counters to track and allocate them right here using
7984 * stktable_alloc_data_type().
7985 */
7986 }
7987 }
7988
Baptiste Assmanne9544932015-11-03 23:31:35 +01007989 /* parse http-request capture rules to ensure id really exists */
7990 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7991 if (hrqrule->action != ACT_CUSTOM ||
7992 hrqrule->action_ptr != http_action_req_capture_by_id)
7993 continue;
7994
7995 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7996 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7997 curproxy->id, hrqrule->arg.capid.idx);
7998 cfgerr++;
7999 }
8000 }
8001
8002 /* parse http-response capture rules to ensure id really exists */
8003 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8004 if (hrqrule->action != ACT_CUSTOM ||
8005 hrqrule->action_ptr != http_action_res_capture_by_id)
8006 continue;
8007
8008 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8009 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8010 curproxy->id, hrqrule->arg.capid.idx);
8011 cfgerr++;
8012 }
8013 }
8014
Willy Tarreau09448f72014-06-25 18:12:15 +02008015 /* find the target table for 'http-request' layer 7 rules */
8016 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8017 struct proxy *target;
8018
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008019 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008020 continue;
8021
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008022 if (hrqrule->arg.trk_ctr.table.n)
8023 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008024 else
8025 target = curproxy;
8026
8027 if (!target) {
8028 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008029 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008030 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008031 cfgerr++;
8032 }
8033 else if (target->table.size == 0) {
8034 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008035 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008036 cfgerr++;
8037 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008038 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008039 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008040 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008041 http_trk_idx(hrqrule->action));
8042 cfgerr++;
8043 }
8044 else {
8045 free(hrqrule->arg.trk_ctr.table.n);
8046 hrqrule->arg.trk_ctr.table.t = &target->table;
8047 /* Note: if we decide to enhance the track-sc syntax, we may be able
8048 * to pass a list of counters to track and allocate them right here using
8049 * stktable_alloc_data_type().
8050 */
8051 }
8052 }
8053
8054 /* find the target table for 'http-response' layer 7 rules */
8055 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8056 struct proxy *target;
8057
8058 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8059 continue;
8060
8061 if (hrqrule->arg.trk_ctr.table.n)
8062 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8063 else
8064 target = curproxy;
8065
8066 if (!target) {
8067 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8068 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8069 http_trk_idx(hrqrule->action));
8070 cfgerr++;
8071 }
8072 else if (target->table.size == 0) {
8073 Alert("Proxy '%s': table '%s' used but not configured.\n",
8074 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8075 cfgerr++;
8076 }
8077 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8078 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8079 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8080 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008081 cfgerr++;
8082 }
8083 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008084 free(hrqrule->arg.trk_ctr.table.n);
8085 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008086 /* Note: if we decide to enhance the track-sc syntax, we may be able
8087 * to pass a list of counters to track and allocate them right here using
8088 * stktable_alloc_data_type().
8089 */
8090 }
8091 }
8092
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008093 /* move any "block" rules at the beginning of the http-request rules */
8094 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8095 /* insert block_rules into http_req_rules at the beginning */
8096 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8097 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8098 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8099 curproxy->http_req_rules.n = curproxy->block_rules.n;
8100 LIST_INIT(&curproxy->block_rules);
8101 }
8102
Emeric Brun32da3c42010-09-23 18:39:19 +02008103 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008104 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008105
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008106 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008107 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8108 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008109 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008110 break;
8111 }
8112 }
8113
8114 if (!curpeers) {
8115 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8116 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008117 free((void *)curproxy->table.peers.name);
8118 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008119 cfgerr++;
8120 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008121 else if (curpeers->state == PR_STSTOPPED) {
8122 /* silently disable this peers section */
8123 curproxy->table.peers.p = NULL;
8124 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008125 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008126 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8127 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008128 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008129 cfgerr++;
8130 }
8131 }
8132
Simon Horman9dc49962015-01-30 11:22:59 +09008133
8134 if (curproxy->email_alert.mailers.name) {
8135 struct mailers *curmailers = mailers;
8136
8137 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8138 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8139 free(curproxy->email_alert.mailers.name);
8140 curproxy->email_alert.mailers.m = curmailers;
8141 curmailers->users++;
8142 break;
8143 }
8144 }
8145
8146 if (!curmailers) {
8147 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8148 curproxy->id, curproxy->email_alert.mailers.name);
8149 free_email_alert(curproxy);
8150 cfgerr++;
8151 }
8152 }
8153
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008154 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008155 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008156 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8157 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8158 "proxy", curproxy->id);
8159 cfgerr++;
8160 goto out_uri_auth_compat;
8161 }
8162
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008163 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008164 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008165 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008166 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008167
Willy Tarreau95fa4692010-02-01 13:05:50 +01008168 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8169 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008170
8171 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008172 uri_auth_compat_req[i++] = "realm";
8173 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8174 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008175
Willy Tarreau95fa4692010-02-01 13:05:50 +01008176 uri_auth_compat_req[i++] = "unless";
8177 uri_auth_compat_req[i++] = "{";
8178 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8179 uri_auth_compat_req[i++] = "}";
8180 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008181
Willy Tarreauff011f22011-01-06 17:51:27 +01008182 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8183 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008184 cfgerr++;
8185 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008186 }
8187
Willy Tarreauff011f22011-01-06 17:51:27 +01008188 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008189
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008190 if (curproxy->uri_auth->auth_realm) {
8191 free(curproxy->uri_auth->auth_realm);
8192 curproxy->uri_auth->auth_realm = NULL;
8193 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008194
8195 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008196 }
8197out_uri_auth_compat:
8198
Dragan Dosen43885c72015-10-01 13:18:13 +02008199 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008200 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008201 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8202 if (!curproxy->conf.logformat_sd_string) {
8203 /* set the default logformat_sd_string */
8204 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8205 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008206 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008207 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008208 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008209
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008210 /* compile the log format */
8211 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008212 if (curproxy->conf.logformat_string != default_http_log_format &&
8213 curproxy->conf.logformat_string != default_tcp_log_format &&
8214 curproxy->conf.logformat_string != clf_http_log_format)
8215 free(curproxy->conf.logformat_string);
8216 curproxy->conf.logformat_string = NULL;
8217 free(curproxy->conf.lfs_file);
8218 curproxy->conf.lfs_file = NULL;
8219 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008220
8221 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8222 free(curproxy->conf.logformat_sd_string);
8223 curproxy->conf.logformat_sd_string = NULL;
8224 free(curproxy->conf.lfsd_file);
8225 curproxy->conf.lfsd_file = NULL;
8226 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008227 }
8228
Willy Tarreau62a61232013-04-12 18:13:46 +02008229 if (curproxy->conf.logformat_string) {
8230 curproxy->conf.args.ctx = ARGC_LOG;
8231 curproxy->conf.args.file = curproxy->conf.lfs_file;
8232 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008233 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008234 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008235 SMP_VAL_FE_LOG_END, &err)) {
8236 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8237 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8238 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008239 cfgerr++;
8240 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008241 curproxy->conf.args.file = NULL;
8242 curproxy->conf.args.line = 0;
8243 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008244
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008245 if (curproxy->conf.logformat_sd_string) {
8246 curproxy->conf.args.ctx = ARGC_LOGSD;
8247 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8248 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008249 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008250 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 +01008251 SMP_VAL_FE_LOG_END, &err)) {
8252 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8253 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8254 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008255 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008256 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8257 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8258 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8259 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008260 cfgerr++;
8261 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008262 curproxy->conf.args.file = NULL;
8263 curproxy->conf.args.line = 0;
8264 }
8265
Willy Tarreau62a61232013-04-12 18:13:46 +02008266 if (curproxy->conf.uniqueid_format_string) {
8267 curproxy->conf.args.ctx = ARGC_UIF;
8268 curproxy->conf.args.file = curproxy->conf.uif_file;
8269 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008270 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008271 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008272 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8273 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8274 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8275 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008276 cfgerr++;
8277 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008278 curproxy->conf.args.file = NULL;
8279 curproxy->conf.args.line = 0;
8280 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008281
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008282 /* only now we can check if some args remain unresolved.
8283 * This must be done after the users and groups resolution.
8284 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008285 cfgerr += smp_resolve_args(curproxy);
8286 if (!cfgerr)
8287 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008288
Willy Tarreau2738a142006-07-08 17:28:09 +02008289 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008290 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008291 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008292 (!curproxy->timeout.connect ||
8293 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008294 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008295 " | While not properly invalid, you will certainly encounter various problems\n"
8296 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008297 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008298 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008299 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008300 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008301
Willy Tarreau1fa31262007-12-03 00:36:16 +01008302 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8303 * We must still support older configurations, so let's find out whether those
8304 * parameters have been set or must be copied from contimeouts.
8305 */
8306 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008307 if (!curproxy->timeout.tarpit ||
8308 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008309 /* tarpit timeout not set. We search in the following order:
8310 * default.tarpit, curr.connect, default.connect.
8311 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008312 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008313 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008314 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008315 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008316 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008317 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008318 }
8319 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008320 (!curproxy->timeout.queue ||
8321 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008322 /* queue timeout not set. We search in the following order:
8323 * default.queue, curr.connect, default.connect.
8324 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008325 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008326 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008327 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008328 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008329 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008330 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008331 }
8332 }
8333
Willy Tarreau1620ec32011-08-06 17:05:02 +02008334 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008335 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008336 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008337 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008338 }
8339
Willy Tarreau215663d2014-06-13 18:30:23 +02008340 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8341 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8342 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8343 proxy_type_str(curproxy), curproxy->id);
8344 err_code |= ERR_WARN;
8345 }
8346
Willy Tarreau193b8c62012-11-22 00:17:38 +01008347 /* ensure that cookie capture length is not too large */
8348 if (curproxy->capture_len >= global.tune.cookie_len) {
8349 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8350 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8351 err_code |= ERR_WARN;
8352 curproxy->capture_len = global.tune.cookie_len - 1;
8353 }
8354
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008355 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008356 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008357 curproxy->req_cap_pool = create_pool("ptrcap",
8358 curproxy->nb_req_cap * sizeof(char *),
8359 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008360 }
8361
8362 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008363 curproxy->rsp_cap_pool = create_pool("ptrcap",
8364 curproxy->nb_rsp_cap * sizeof(char *),
8365 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008366 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008367
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008368 switch (curproxy->load_server_state_from_file) {
8369 case PR_SRV_STATE_FILE_UNSPEC:
8370 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8371 break;
8372 case PR_SRV_STATE_FILE_GLOBAL:
8373 if (!global.server_state_file) {
8374 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",
8375 curproxy->id);
8376 err_code |= ERR_WARN;
8377 }
8378 break;
8379 }
8380
Willy Tarreaubaaee002006-06-26 02:48:02 +02008381 /* first, we will invert the servers list order */
8382 newsrv = NULL;
8383 while (curproxy->srv) {
8384 struct server *next;
8385
8386 next = curproxy->srv->next;
8387 curproxy->srv->next = newsrv;
8388 newsrv = curproxy->srv;
8389 if (!next)
8390 break;
8391 curproxy->srv = next;
8392 }
8393
Willy Tarreau17edc812014-01-03 12:14:34 +01008394 /* Check that no server name conflicts. This causes trouble in the stats.
8395 * We only emit a warning for the first conflict affecting each server,
8396 * in order to avoid combinatory explosion if all servers have the same
8397 * name. We do that only for servers which do not have an explicit ID,
8398 * because these IDs were made also for distinguishing them and we don't
8399 * want to annoy people who correctly manage them.
8400 */
8401 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8402 struct server *other_srv;
8403
8404 if (newsrv->puid)
8405 continue;
8406
8407 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8408 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8409 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8410 newsrv->conf.file, newsrv->conf.line,
8411 proxy_type_str(curproxy), curproxy->id,
8412 newsrv->id, other_srv->conf.line);
8413 break;
8414 }
8415 }
8416 }
8417
Willy Tarreaudd701652010-05-25 23:03:02 +02008418 /* assign automatic UIDs to servers which don't have one yet */
8419 next_id = 1;
8420 newsrv = curproxy->srv;
8421 while (newsrv != NULL) {
8422 if (!newsrv->puid) {
8423 /* server ID not set, use automatic numbering with first
8424 * spare entry starting with next_svid.
8425 */
8426 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8427 newsrv->conf.id.key = newsrv->puid = next_id;
8428 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8429 }
8430 next_id++;
8431 newsrv = newsrv->next;
8432 }
8433
Willy Tarreau20697042007-11-15 23:26:18 +01008434 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008435 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008436
Willy Tarreau62c3be22012-01-20 13:12:32 +01008437 /*
8438 * If this server supports a maxconn parameter, it needs a dedicated
8439 * tasks to fill the emptied slots when a connection leaves.
8440 * Also, resolve deferred tracking dependency if needed.
8441 */
8442 newsrv = curproxy->srv;
8443 while (newsrv != NULL) {
8444 if (newsrv->minconn > newsrv->maxconn) {
8445 /* Only 'minconn' was specified, or it was higher than or equal
8446 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8447 * this will avoid further useless expensive computations.
8448 */
8449 newsrv->maxconn = newsrv->minconn;
8450 } else if (newsrv->maxconn && !newsrv->minconn) {
8451 /* minconn was not specified, so we set it to maxconn */
8452 newsrv->minconn = newsrv->maxconn;
8453 }
8454
Willy Tarreau17d45382016-12-22 21:16:08 +01008455 /* this will also properly set the transport layer for prod and checks */
8456 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8457 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8458 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8459 }
Emeric Brun94324a42012-10-11 14:00:19 +02008460
Willy Tarreau2f075e92013-12-03 11:11:34 +01008461 /* set the check type on the server */
8462 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8463
Willy Tarreau62c3be22012-01-20 13:12:32 +01008464 if (newsrv->trackit) {
8465 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008466 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008467 char *pname, *sname;
8468
8469 pname = newsrv->trackit;
8470 sname = strrchr(pname, '/');
8471
8472 if (sname)
8473 *sname++ = '\0';
8474 else {
8475 sname = pname;
8476 pname = NULL;
8477 }
8478
8479 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008480 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008481 if (!px) {
8482 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8483 proxy_type_str(curproxy), curproxy->id,
8484 newsrv->id, pname);
8485 cfgerr++;
8486 goto next_srv;
8487 }
8488 } else
8489 px = curproxy;
8490
8491 srv = findserver(px, sname);
8492 if (!srv) {
8493 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8494 proxy_type_str(curproxy), curproxy->id,
8495 newsrv->id, sname);
8496 cfgerr++;
8497 goto next_srv;
8498 }
8499
Willy Tarreau32091232014-05-16 13:52:00 +02008500 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8501 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8502 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008503 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008504 "tracking as it does not have any check nor agent enabled.\n",
8505 proxy_type_str(curproxy), curproxy->id,
8506 newsrv->id, px->id, srv->id);
8507 cfgerr++;
8508 goto next_srv;
8509 }
8510
8511 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8512
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008513 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008514 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8515 "belongs to a tracking chain looping back to %s/%s.\n",
8516 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008517 newsrv->id, px->id, srv->id, px->id,
8518 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008519 cfgerr++;
8520 goto next_srv;
8521 }
8522
8523 if (curproxy != px &&
8524 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8525 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8526 "tracking: disable-on-404 option inconsistency.\n",
8527 proxy_type_str(curproxy), curproxy->id,
8528 newsrv->id, px->id, srv->id);
8529 cfgerr++;
8530 goto next_srv;
8531 }
8532
Willy Tarreau62c3be22012-01-20 13:12:32 +01008533 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008534 newsrv->tracknext = srv->trackers;
8535 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008536
8537 free(newsrv->trackit);
8538 newsrv->trackit = NULL;
8539 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008540
8541 /*
8542 * resolve server's resolvers name and update the resolvers pointer
8543 * accordingly
8544 */
8545 if (newsrv->resolvers_id) {
8546 struct dns_resolvers *curr_resolvers;
8547 int found;
8548
8549 found = 0;
8550 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8551 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8552 found = 1;
8553 break;
8554 }
8555 }
8556
8557 if (!found) {
8558 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8559 proxy_type_str(curproxy), curproxy->id,
8560 newsrv->id, newsrv->resolvers_id);
8561 cfgerr++;
8562 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008563 if (newsrv->srvrq) {
8564 if (!newsrv->srvrq->resolvers) {
8565 newsrv->srvrq->resolvers = curr_resolvers;
8566 if (dns_link_resolution(newsrv->srvrq,
8567 OBJ_TYPE_SRVRQ, NULL) != 0) {
8568 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8569 proxy_type_str(curproxy), curproxy->id,
8570 newsrv->id);
8571 cfgerr++;
8572 }
8573 }
8574
8575 }
8576 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008577 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008578 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8579 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8580 proxy_type_str(curproxy), curproxy->id,
8581 newsrv->id);
8582 cfgerr++;
8583 }
8584 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008585 }
8586 }
8587 else {
8588 /* if no resolvers section associated to this server
8589 * we can clean up the associated resolution structure
8590 */
8591 if (newsrv->resolution) {
8592 free(newsrv->resolution->hostname_dn);
8593 newsrv->resolution->hostname_dn = NULL;
8594 free(newsrv->resolution);
8595 newsrv->resolution = NULL;
8596 }
8597 }
8598
Willy Tarreau62c3be22012-01-20 13:12:32 +01008599 next_srv:
8600 newsrv = newsrv->next;
8601 }
8602
Olivier Houchard4e694042017-03-14 20:01:29 +01008603 /*
8604 * Try to generate dynamic cookies for servers now.
8605 * It couldn't be done earlier, since at the time we parsed
8606 * the server line, we may not have known yet that we
8607 * should use dynamic cookies, or the secret key may not
8608 * have been provided yet.
8609 */
8610 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8611 newsrv = curproxy->srv;
8612 while (newsrv != NULL) {
8613 srv_set_dyncookie(newsrv);
8614 newsrv = newsrv->next;
8615 }
8616
8617 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008618 /* We have to initialize the server lookup mechanism depending
8619 * on what LB algorithm was choosen.
8620 */
8621
8622 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8623 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8624 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008625 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8626 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8627 init_server_map(curproxy);
8628 } else {
8629 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8630 fwrr_init_server_groups(curproxy);
8631 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008632 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008633
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008634 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008635 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8636 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8637 fwlc_init_server_tree(curproxy);
8638 } else {
8639 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8640 fas_init_server_tree(curproxy);
8641 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008642 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008643
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008644 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008645 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8646 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8647 chash_init_server_tree(curproxy);
8648 } else {
8649 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8650 init_server_map(curproxy);
8651 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008652 break;
8653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008654
8655 if (curproxy->options & PR_O_LOGASAP)
8656 curproxy->to_log &= ~LW_BYTES;
8657
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008658 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008659 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8660 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008661 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8662 proxy_type_str(curproxy), curproxy->id);
8663 err_code |= ERR_WARN;
8664 }
8665
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008666 if (curproxy->mode != PR_MODE_HTTP) {
8667 int optnum;
8668
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008669 if (curproxy->uri_auth) {
8670 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8671 proxy_type_str(curproxy), curproxy->id);
8672 err_code |= ERR_WARN;
8673 curproxy->uri_auth = NULL;
8674 }
8675
Willy Tarreaude7dc882017-03-10 11:49:21 +01008676 if (curproxy->capture_name) {
8677 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8678 proxy_type_str(curproxy), curproxy->id);
8679 err_code |= ERR_WARN;
8680 }
8681
8682 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8683 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8684 proxy_type_str(curproxy), curproxy->id);
8685 err_code |= ERR_WARN;
8686 }
8687
8688 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8689 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8690 proxy_type_str(curproxy), curproxy->id);
8691 err_code |= ERR_WARN;
8692 }
8693
8694 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8695 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8696 proxy_type_str(curproxy), curproxy->id);
8697 err_code |= ERR_WARN;
8698 }
8699
8700 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8701 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8702 proxy_type_str(curproxy), curproxy->id);
8703 err_code |= ERR_WARN;
8704 }
8705
Willy Tarreau87cf5142011-08-19 22:57:24 +02008706 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008707 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8708 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8709 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008710 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008711 }
8712
8713 if (curproxy->options & PR_O_ORGTO) {
8714 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8715 "originalto", proxy_type_str(curproxy), curproxy->id);
8716 err_code |= ERR_WARN;
8717 curproxy->options &= ~PR_O_ORGTO;
8718 }
8719
8720 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8721 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8722 (curproxy->cap & cfg_opts[optnum].cap) &&
8723 (curproxy->options & cfg_opts[optnum].val)) {
8724 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8725 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8726 err_code |= ERR_WARN;
8727 curproxy->options &= ~cfg_opts[optnum].val;
8728 }
8729 }
8730
8731 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8732 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8733 (curproxy->cap & cfg_opts2[optnum].cap) &&
8734 (curproxy->options2 & cfg_opts2[optnum].val)) {
8735 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8736 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8737 err_code |= ERR_WARN;
8738 curproxy->options2 &= ~cfg_opts2[optnum].val;
8739 }
8740 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008741
Willy Tarreau29fbe512015-08-20 19:35:14 +02008742#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008743 if (curproxy->conn_src.bind_hdr_occ) {
8744 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008745 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008746 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008747 err_code |= ERR_WARN;
8748 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008749#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008750 }
8751
Willy Tarreaubaaee002006-06-26 02:48:02 +02008752 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008753 * ensure that we're not cross-dressing a TCP server into HTTP.
8754 */
8755 newsrv = curproxy->srv;
8756 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008757 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008758 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8759 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008760 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008761 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008762
Willy Tarreau0cec3312011-10-31 13:49:26 +01008763 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8764 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8765 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8766 err_code |= ERR_WARN;
8767 }
8768
Willy Tarreauc93cd162014-05-13 15:54:22 +02008769 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008770 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8771 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8772 err_code |= ERR_WARN;
8773 }
8774
Willy Tarreau29fbe512015-08-20 19:35:14 +02008775#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008776 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8777 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008778 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 +01008779 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008780 err_code |= ERR_WARN;
8781 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008782#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008783
8784 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8785 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8786 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8787 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8788 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8789 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",
8790 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8791 err_code |= ERR_WARN;
8792 }
8793
8794
8795 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8796 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",
8797 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8798 err_code |= ERR_WARN;
8799 }
8800 }
8801
Willy Tarreau21d2af32008-02-14 20:25:24 +01008802 newsrv = newsrv->next;
8803 }
8804
Willy Tarreaue42bd962014-09-16 16:21:19 +02008805 /* check if we have a frontend with "tcp-request content" looking at L7
8806 * with no inspect-delay
8807 */
8808 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8809 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008810 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008811 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008812 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008813 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008814 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008815 break;
8816 }
8817
8818 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8819 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8820 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8821 " This means that these rules will randomly find their contents. This can be fixed by"
8822 " setting the tcp-request inspect-delay.\n",
8823 proxy_type_str(curproxy), curproxy->id);
8824 err_code |= ERR_WARN;
8825 }
8826 }
8827
Christopher Fauletd7c91962015-04-30 11:48:27 +02008828 /* Check filter configuration, if any */
8829 cfgerr += flt_check(curproxy);
8830
Willy Tarreauc1a21672009-08-16 22:37:44 +02008831 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008832 if (!curproxy->accept)
8833 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008834
Willy Tarreauc1a21672009-08-16 22:37:44 +02008835 if (curproxy->tcp_req.inspect_delay ||
8836 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008837 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008838
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008839 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008840 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008841 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008842 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008843
8844 /* both TCP and HTTP must check switching rules */
8845 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008846
8847 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008848 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008849 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8850 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 +01008851 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008852 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8853 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008854 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008855 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008856 }
8857
8858 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008859 if (curproxy->tcp_req.inspect_delay ||
8860 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8861 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8862
Emeric Brun97679e72010-09-23 17:56:44 +02008863 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8864 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8865
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008866 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008867 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008868 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008869 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008870
8871 /* If the backend does requires RDP cookie persistence, we have to
8872 * enable the corresponding analyser.
8873 */
8874 if (curproxy->options2 & PR_O2_RDPC_PRST)
8875 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008876
8877 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008878 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008879 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8880 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 +01008881 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008882 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8883 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008884 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008885 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008886 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008887 }
8888
8889 /***********************************************************/
8890 /* At this point, target names have already been resolved. */
8891 /***********************************************************/
8892
8893 /* Check multi-process mode compatibility */
8894
8895 if (global.nbproc > 1 && global.stats_fe) {
8896 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8897 unsigned long mask;
8898
8899 mask = nbits(global.nbproc);
8900 if (global.stats_fe->bind_proc)
8901 mask &= global.stats_fe->bind_proc;
8902
8903 if (bind_conf->bind_proc)
8904 mask &= bind_conf->bind_proc;
8905
8906 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008907 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008908 break;
8909 }
8910 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8911 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");
8912 }
8913 }
8914
8915 /* Make each frontend inherit bind-process from its listeners when not specified. */
8916 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8917 if (curproxy->bind_proc)
8918 continue;
8919
8920 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8921 unsigned long mask;
8922
Willy Tarreaue428b082015-05-04 21:57:58 +02008923 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008924 curproxy->bind_proc |= mask;
8925 }
8926
8927 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008928 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008929 }
8930
8931 if (global.stats_fe) {
8932 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8933 unsigned long mask;
8934
Cyril Bonté06181952016-02-24 00:14:54 +01008935 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008936 global.stats_fe->bind_proc |= mask;
8937 }
8938 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008939 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008940 }
8941
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008942 /* propagate bindings from frontends to backends. Don't do it if there
8943 * are any fatal errors as we must not call it with unresolved proxies.
8944 */
8945 if (!cfgerr) {
8946 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8947 if (curproxy->cap & PR_CAP_FE)
8948 propagate_processes(curproxy, NULL);
8949 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008950 }
8951
8952 /* Bind each unbound backend to all processes when not specified. */
8953 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8954 if (curproxy->bind_proc)
8955 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008956 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008957 }
8958
8959 /*******************************************************/
8960 /* At this step, all proxies have a non-null bind_proc */
8961 /*******************************************************/
8962
8963 /* perform the final checks before creating tasks */
8964
8965 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8966 struct listener *listener;
8967 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008968
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008969 /* Configure SSL for each bind line.
8970 * Note: if configuration fails at some point, the ->ctx member
8971 * remains NULL so that listeners can later detach.
8972 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008973 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008974 if (bind_conf->xprt->prepare_bind_conf &&
8975 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008976 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008977 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008978
Willy Tarreaue6b98942007-10-29 01:09:36 +01008979 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008980 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008981 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008982 int nbproc;
8983
8984 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008985 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008986 nbits(global.nbproc));
8987
8988 if (!nbproc) /* no intersection between listener and frontend */
8989 nbproc = 1;
8990
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008991 if (!listener->luid) {
8992 /* listener ID not set, use automatic numbering with first
8993 * spare entry starting with next_luid.
8994 */
8995 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8996 listener->conf.id.key = listener->luid = next_id;
8997 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008998 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008999 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009000
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009001 /* enable separate counters */
9002 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01009003 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009004 if (!listener->name)
9005 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009006 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009007
Willy Tarreaue6b98942007-10-29 01:09:36 +01009008 if (curproxy->options & PR_O_TCP_NOLING)
9009 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009010 if (!listener->maxconn)
9011 listener->maxconn = curproxy->maxconn;
9012 if (!listener->backlog)
9013 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009014 if (!listener->maxaccept)
9015 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9016
9017 /* we want to have an optimal behaviour on single process mode to
9018 * maximize the work at once, but in multi-process we want to keep
9019 * some fairness between processes, so we target half of the max
9020 * number of events to be balanced over all the processes the proxy
9021 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9022 * used to disable the limit.
9023 */
9024 if (listener->maxaccept > 0) {
9025 if (nbproc > 1)
9026 listener->maxaccept = (listener->maxaccept + 1) / 2;
9027 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9028 }
9029
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009030 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009031 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009032 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009033 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009034
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009035 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009036 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009037
Willy Tarreau620408f2016-10-21 16:37:51 +02009038 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9039 listener->options |= LI_O_TCP_L5_RULES;
9040
Willy Tarreaude3041d2010-05-31 10:56:17 +02009041 if (curproxy->mon_mask.s_addr)
9042 listener->options |= LI_O_CHK_MONNET;
9043
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009044 /* smart accept mode is automatic in HTTP mode */
9045 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009046 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009047 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9048 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009049 }
9050
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009051 /* Release unused SSL configs */
9052 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009053 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9054 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009055 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009056
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009057 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009058 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009059 int count, maxproc = 0;
9060
9061 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009062 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009063 if (count > maxproc)
9064 maxproc = count;
9065 }
9066 /* backends have 0, frontends have 1 or more */
9067 if (maxproc != 1)
9068 Warning("Proxy '%s': in multi-process mode, stats will be"
9069 " limited to process assigned to the current request.\n",
9070 curproxy->id);
9071
Willy Tarreau102df612014-05-07 23:56:38 +02009072 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9073 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9074 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009075 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009076 }
Willy Tarreau102df612014-05-07 23:56:38 +02009077 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9078 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9079 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009080 }
9081 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009082
9083 /* create the task associated with the proxy */
9084 curproxy->task = task_new();
9085 if (curproxy->task) {
9086 curproxy->task->context = curproxy;
9087 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009088 } else {
9089 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9090 curproxy->id);
9091 cfgerr++;
9092 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009093 }
9094
Willy Tarreaufbb78422011-06-05 15:38:35 +02009095 /* automatically compute fullconn if not set. We must not do it in the
9096 * loop above because cross-references are not yet fully resolved.
9097 */
9098 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9099 /* If <fullconn> is not set, let's set it to 10% of the sum of
9100 * the possible incoming frontend's maxconns.
9101 */
9102 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009103 /* we have the sum of the maxconns in <total>. We only
9104 * keep 10% of that sum to set the default fullconn, with
9105 * a hard minimum of 1 (to avoid a divide by zero).
9106 */
Emeric Brun3f783572017-01-12 11:21:28 +01009107 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009108 if (!curproxy->fullconn)
9109 curproxy->fullconn = 1;
9110 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009111 }
9112
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009113 /*
9114 * Recount currently required checks.
9115 */
9116
9117 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9118 int optnum;
9119
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009120 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9121 if (curproxy->options & cfg_opts[optnum].val)
9122 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009123
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009124 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9125 if (curproxy->options2 & cfg_opts2[optnum].val)
9126 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009127 }
9128
Willy Tarreau0fca4832015-05-01 19:12:05 +02009129 /* compute the required process bindings for the peers */
9130 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9131 if (curproxy->table.peers.p)
9132 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9133
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009134 if (cfg_peers) {
9135 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009136 struct peer *p, *pb;
9137
Willy Tarreau1e273012015-05-01 19:15:17 +02009138 /* Remove all peers sections which don't have a valid listener,
9139 * which are not used by any table, or which are bound to more
9140 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009141 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009142 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009143 while (*last) {
9144 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009145
9146 if (curpeers->state == PR_STSTOPPED) {
9147 /* the "disabled" keyword was present */
9148 if (curpeers->peers_fe)
9149 stop_proxy(curpeers->peers_fe);
9150 curpeers->peers_fe = NULL;
9151 }
9152 else if (!curpeers->peers_fe) {
9153 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9154 curpeers->id, localpeer);
9155 }
David Carliere6c39412015-07-02 07:00:17 +00009156 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009157 /* either it's totally stopped or too much used */
9158 if (curpeers->peers_fe->bind_proc) {
9159 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009160 "running in different processes (%d different ones). "
9161 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009162 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009163 cfgerr++;
9164 }
9165 stop_proxy(curpeers->peers_fe);
9166 curpeers->peers_fe = NULL;
9167 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009168 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009169 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009170 last = &curpeers->next;
9171 continue;
9172 }
9173
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009174 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009175 p = curpeers->remote;
9176 while (p) {
9177 pb = p->next;
9178 free(p->id);
9179 free(p);
9180 p = pb;
9181 }
9182
9183 /* Destroy and unlink this curpeers section.
9184 * Note: curpeers is backed up into *last.
9185 */
9186 free(curpeers->id);
9187 curpeers = curpeers->next;
9188 free(*last);
9189 *last = curpeers;
9190 }
9191 }
9192
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009193 /* initialize stick-tables on backend capable proxies. This must not
9194 * be done earlier because the data size may be discovered while parsing
9195 * other proxies.
9196 */
9197 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9198 if (curproxy->state == PR_STSTOPPED)
9199 continue;
9200
9201 if (!stktable_init(&curproxy->table)) {
9202 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9203 cfgerr++;
9204 }
9205 }
9206
Simon Horman0d16a402015-01-30 11:22:58 +09009207 if (mailers) {
9208 struct mailers *curmailers = mailers, **last;
9209 struct mailer *m, *mb;
9210
9211 /* Remove all mailers sections which don't have a valid listener.
9212 * This can happen when a mailers section is never referenced.
9213 */
9214 last = &mailers;
9215 while (*last) {
9216 curmailers = *last;
9217 if (curmailers->users) {
9218 last = &curmailers->next;
9219 continue;
9220 }
9221
9222 Warning("Removing incomplete section 'mailers %s'.\n",
9223 curmailers->id);
9224
9225 m = curmailers->mailer_list;
9226 while (m) {
9227 mb = m->next;
9228 free(m->id);
9229 free(m);
9230 m = mb;
9231 }
9232
9233 /* Destroy and unlink this curmailers section.
9234 * Note: curmailers is backed up into *last.
9235 */
9236 free(curmailers->id);
9237 curmailers = curmailers->next;
9238 free(*last);
9239 *last = curmailers;
9240 }
9241 }
9242
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009243 /* Update server_state_file_name to backend name if backend is supposed to use
9244 * a server-state file locally defined and none has been provided */
9245 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9246 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9247 curproxy->server_state_file_name == NULL)
9248 curproxy->server_state_file_name = strdup(curproxy->id);
9249 }
9250
Willy Tarreau34eb6712011-10-24 18:15:04 +02009251 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009252 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009253 MEM_F_SHARED);
9254
Willy Tarreaubb925012009-07-23 13:36:36 +02009255 if (cfgerr > 0)
9256 err_code |= ERR_ALERT | ERR_FATAL;
9257 out:
9258 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009259}
9260
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009261/*
9262 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9263 * parsing sessions.
9264 */
9265void cfg_register_keywords(struct cfg_kw_list *kwl)
9266{
9267 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9268}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009269
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009270/*
9271 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9272 */
9273void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9274{
9275 LIST_DEL(&kwl->list);
9276 LIST_INIT(&kwl->list);
9277}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009278
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009279/* this function register new section in the haproxy configuration file.
9280 * <section_name> is the name of this new section and <section_parser>
9281 * is the called parser. If two section declaration have the same name,
9282 * only the first declared is used.
9283 */
9284int cfg_register_section(char *section_name,
9285 int (*section_parser)(const char *, int, char **, int))
9286{
9287 struct cfg_section *cs;
9288
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009289 list_for_each_entry(cs, &sections, list) {
9290 if (strcmp(cs->section_name, section_name) == 0) {
9291 Alert("register section '%s': already registered.\n", section_name);
9292 return 0;
9293 }
9294 }
9295
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009296 cs = calloc(1, sizeof(*cs));
9297 if (!cs) {
9298 Alert("register section '%s': out of memory.\n", section_name);
9299 return 0;
9300 }
9301
9302 cs->section_name = section_name;
9303 cs->section_parser = section_parser;
9304
9305 LIST_ADDQ(&sections, &cs->list);
9306
9307 return 1;
9308}
9309
Willy Tarreaubaaee002006-06-26 02:48:02 +02009310/*
David Carlier845efb52015-09-25 11:49:18 +01009311 * free all config section entries
9312 */
9313void cfg_unregister_sections(void)
9314{
9315 struct cfg_section *cs, *ics;
9316
9317 list_for_each_entry_safe(cs, ics, &sections, list) {
9318 LIST_DEL(&cs->list);
9319 free(cs);
9320 }
9321}
9322
Christopher Faulet7110b402016-10-26 11:09:44 +02009323void cfg_backup_sections(struct list *backup_sections)
9324{
9325 struct cfg_section *cs, *ics;
9326
9327 list_for_each_entry_safe(cs, ics, &sections, list) {
9328 LIST_DEL(&cs->list);
9329 LIST_ADDQ(backup_sections, &cs->list);
9330 }
9331}
9332
9333void cfg_restore_sections(struct list *backup_sections)
9334{
9335 struct cfg_section *cs, *ics;
9336
9337 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9338 LIST_DEL(&cs->list);
9339 LIST_ADDQ(&sections, &cs->list);
9340 }
9341}
9342
Willy Tarreau659fbf02016-05-26 17:55:28 +02009343__attribute__((constructor))
9344static void cfgparse_init(void)
9345{
9346 /* Register internal sections */
9347 cfg_register_section("listen", cfg_parse_listen);
9348 cfg_register_section("frontend", cfg_parse_listen);
9349 cfg_register_section("backend", cfg_parse_listen);
9350 cfg_register_section("defaults", cfg_parse_listen);
9351 cfg_register_section("global", cfg_parse_global);
9352 cfg_register_section("userlist", cfg_parse_users);
9353 cfg_register_section("peers", cfg_parse_peers);
9354 cfg_register_section("mailers", cfg_parse_mailers);
9355 cfg_register_section("namespace_list", cfg_parse_netns);
9356 cfg_register_section("resolvers", cfg_parse_resolvers);
9357}
9358
David Carlier845efb52015-09-25 11:49:18 +01009359/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009360 * Local variables:
9361 * c-indent-level: 8
9362 * c-basic-offset: 8
9363 * End:
9364 */