blob: c2115e6a2b808a078f104aec99006c578377b87f [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 Tarreau27a674e2009-08-17 07:23:33 +0200776 }
777 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200778 if (alertif_too_many_args(1, file, linenum, args, &err_code))
779 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200786 if (global.tune.maxrewrite < 0) {
787 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
790 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200791 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100792 else if (!strcmp(args[0], "tune.idletimer")) {
793 unsigned int idle;
794 const char *res;
795
William Lallemand1a748ae2015-05-19 16:37:23 +0200796 if (alertif_too_many_args(1, file, linenum, args, &err_code))
797 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
805 if (res) {
806 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
807 file, linenum, *res, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811
812 if (idle > 65535) {
813 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.idle_timer = idle;
818 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100819 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200820 if (alertif_too_many_args(1, file, linenum, args, &err_code))
821 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100822 if (global.tune.client_rcvbuf != 0) {
823 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
824 err_code |= ERR_ALERT;
825 goto out;
826 }
827 if (*(args[1]) == 0) {
828 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 global.tune.client_rcvbuf = atol(args[1]);
833 }
834 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100837 if (global.tune.server_rcvbuf != 0) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT;
840 goto out;
841 }
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.server_rcvbuf = atol(args[1]);
848 }
849 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100852 if (global.tune.client_sndbuf != 0) {
853 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT;
855 goto out;
856 }
857 if (*(args[1]) == 0) {
858 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 global.tune.client_sndbuf = atol(args[1]);
863 }
864 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200865 if (alertif_too_many_args(1, file, linenum, args, &err_code))
866 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100867 if (global.tune.server_sndbuf != 0) {
868 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT;
870 goto out;
871 }
872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877 global.tune.server_sndbuf = atol(args[1]);
878 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200879 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200880 if (alertif_too_many_args(1, file, linenum, args, &err_code))
881 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200882 if (*(args[1]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887 global.tune.pipesize = atol(args[1]);
888 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100889 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200890 if (alertif_too_many_args(1, file, linenum, args, &err_code))
891 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100892 if (*(args[1]) == 0) {
893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
897 global.tune.cookie_len = atol(args[1]) + 1;
898 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200899 else if (!strcmp(args[0], "tune.http.logurilen")) {
900 if (alertif_too_many_args(1, file, linenum, args, &err_code))
901 goto out;
902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 global.tune.requri_len = atol(args[1]) + 1;
908 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200909 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200910 if (alertif_too_many_args(1, file, linenum, args, &err_code))
911 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200912 if (*(args[1]) == 0) {
913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
Christopher Faulet50174f32017-06-21 16:31:35 +0200917 global.tune.max_http_hdr = atoi(args[1]);
918 if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
919 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
920 file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200924 }
William Lallemandf3747832012-11-09 12:33:10 +0100925 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
927 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100928 if (*args[1]) {
929 global.tune.comp_maxlevel = atoi(args[1]);
930 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
931 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
932 file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 } else {
937 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
938 file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200943 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
944 if (*args[1]) {
945 global.tune.pattern_cache = atoi(args[1]);
946 if (global.tune.pattern_cache < 0) {
947 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
948 file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 } else {
953 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
954 file, linenum, args[0]);
955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
957 }
958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200960 if (alertif_too_many_args(1, file, linenum, args, &err_code))
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200963 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT;
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100972 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
973 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]);
974 err_code |= ERR_WARN;
975 goto out;
976 }
977
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200980 if (alertif_too_many_args(1, file, linenum, args, &err_code))
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200983 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT;
985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100992 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
993 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]);
994 err_code |= ERR_WARN;
995 goto out;
996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
Simon Horman98637e52014-06-20 12:30:16 +0900998 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200999 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1000 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001001 global.external_check = 1;
1002 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001003 /* user/group name handling */
1004 else if (!strcmp(args[0], "user")) {
1005 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1007 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001008 if (global.uid != 0) {
1009 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT;
1011 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001012 }
1013 errno = 0;
1014 ha_user = getpwnam(args[1]);
1015 if (ha_user != NULL) {
1016 global.uid = (int)ha_user->pw_uid;
1017 }
1018 else {
1019 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 +02001020 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001021 }
1022 }
1023 else if (!strcmp(args[0], "group")) {
1024 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001025 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1026 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001027 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001028 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT;
1030 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001031 }
1032 errno = 0;
1033 ha_group = getgrnam(args[1]);
1034 if (ha_group != NULL) {
1035 global.gid = (int)ha_group->gr_gid;
1036 }
1037 else {
1038 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 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001040 }
1041 }
1042 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001044 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 if (*(args[1]) == 0) {
1047 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 }
1051 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001052 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1053 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1054 file, linenum, args[0], LONGBITS, global.nbproc);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001060 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 if (global.maxconn != 0) {
1063 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 err_code |= ERR_ALERT;
1065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 }
1067 if (*(args[1]) == 0) {
1068 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 }
1072 global.maxconn = atol(args[1]);
1073#ifdef SYSTEM_MAXCONN
1074 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1075 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);
1076 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 }
1079#endif /* SYSTEM_MAXCONN */
1080 }
Emeric Brun850efd52014-01-29 12:24:34 +01001081 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001082 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1083 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 if (strcmp(args[1],"none") == 0)
1090 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1091 else if (strcmp(args[1],"required") == 0)
1092 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1093 else {
1094 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001099 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001100 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1101 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001102 if (global.cps_lim != 0) {
1103 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT;
1105 goto out;
1106 }
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 global.cps_lim = atol(args[1]);
1113 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001114 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001115 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1116 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001117 if (global.sps_lim != 0) {
1118 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT;
1120 goto out;
1121 }
1122 if (*(args[1]) == 0) {
1123 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
1126 }
1127 global.sps_lim = atol(args[1]);
1128 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001129 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001130 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1131 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001132 if (global.ssl_lim != 0) {
1133 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1134 err_code |= ERR_ALERT;
1135 goto out;
1136 }
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
1141 }
1142 global.ssl_lim = atol(args[1]);
1143 }
William Lallemandd85f9172012-11-09 17:05:39 +01001144 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152 global.comp_rate_lim = atoi(args[1]) * 1024;
1153 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001154 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1156 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001157 if (global.maxpipes != 0) {
1158 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT;
1160 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001161 }
1162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001166 }
1167 global.maxpipes = atol(args[1]);
1168 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001169 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001170 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1171 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001172 if (*(args[1]) == 0) {
1173 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
1176 }
William Lallemande3a7d992012-11-20 11:25:20 +01001177 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001178 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001179 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001188 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001189 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
1192 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001193 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001194
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 if (global.rlimit_nofile != 0) {
1199 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 }
1208 global.rlimit_nofile = atol(args[1]);
1209 }
1210 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 if (global.chroot != NULL) {
1214 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 if (*(args[1]) == 0) {
1219 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 }
1223 global.chroot = strdup(args[1]);
1224 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001225 else if (!strcmp(args[0], "description")) {
1226 int i, len=0;
1227 char *d;
1228
1229 if (!*args[1]) {
1230 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
Willy Tarreau348acfe2014-04-14 15:00:39 +02001236 for (i = 1; *args[i]; i++)
1237 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001238
1239 if (global.desc)
1240 free(global.desc);
1241
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001242 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001243
Willy Tarreau348acfe2014-04-14 15:00:39 +02001244 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1245 for (i = 2; *args[i]; i++)
1246 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001247 }
1248 else if (!strcmp(args[0], "node")) {
1249 int i;
1250 char c;
1251
William Lallemand1a748ae2015-05-19 16:37:23 +02001252 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1253 goto out;
1254
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001255 for (i=0; args[1][i]; i++) {
1256 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001257 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1258 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001259 break;
1260 }
1261
1262 if (!i || args[1][i]) {
1263 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1264 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1265 file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269
1270 if (global.node)
1271 free(global.node);
1272
1273 global.node = strdup(args[1]);
1274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001276 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 if (global.pidfile != NULL) {
1279 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT;
1281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
1283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 }
1288 global.pidfile = strdup(args[1]);
1289 }
Emeric Bruned760922010-10-22 17:59:25 +02001290 else if (!strcmp(args[0], "unix-bind")) {
1291 int cur_arg = 1;
1292 while (*(args[cur_arg])) {
1293 if (!strcmp(args[cur_arg], "prefix")) {
1294 if (global.unix_bind.prefix != NULL) {
1295 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1296 err_code |= ERR_ALERT;
1297 cur_arg += 2;
1298 continue;
1299 }
1300
1301 if (*(args[cur_arg+1]) == 0) {
1302 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1307 cur_arg += 2;
1308 continue;
1309 }
1310
1311 if (!strcmp(args[cur_arg], "mode")) {
1312
1313 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1314 cur_arg += 2;
1315 continue;
1316 }
1317
1318 if (!strcmp(args[cur_arg], "uid")) {
1319
1320 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1321 cur_arg += 2;
1322 continue;
1323 }
1324
1325 if (!strcmp(args[cur_arg], "gid")) {
1326
1327 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1328 cur_arg += 2;
1329 continue;
1330 }
1331
1332 if (!strcmp(args[cur_arg], "user")) {
1333 struct passwd *user;
1334
1335 user = getpwnam(args[cur_arg + 1]);
1336 if (!user) {
1337 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1338 file, linenum, args[0], args[cur_arg + 1 ]);
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343 global.unix_bind.ux.uid = user->pw_uid;
1344 cur_arg += 2;
1345 continue;
1346 }
1347
1348 if (!strcmp(args[cur_arg], "group")) {
1349 struct group *group;
1350
1351 group = getgrnam(args[cur_arg + 1]);
1352 if (!group) {
1353 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1354 file, linenum, args[0], args[cur_arg + 1 ]);
1355 err_code |= ERR_ALERT | ERR_FATAL;
1356 goto out;
1357 }
1358
1359 global.unix_bind.ux.gid = group->gr_gid;
1360 cur_arg += 2;
1361 continue;
1362 }
1363
Willy Tarreaub48f9582011-09-05 01:17:06 +02001364 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001365 file, linenum, args[0]);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
1368 }
1369 }
William Lallemand0f99e342011-10-12 17:50:54 +02001370 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1371 /* delete previous herited or defined syslog servers */
1372 struct logsrv *back;
1373 struct logsrv *tmp;
1374
1375 if (*(args[1]) != 0) {
1376 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380
1381 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1382 LIST_DEL(&tmp->list);
1383 free(tmp);
1384 }
1385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001387 struct sockaddr_storage *sk;
1388 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001389 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001390 int arg = 0;
1391 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001392
William Lallemand1a748ae2015-05-19 16:37:23 +02001393 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1394 goto out;
1395
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (*(args[1]) == 0 || *(args[2]) == 0) {
1397 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
William Lallemand0f99e342011-10-12 17:50:54 +02001401
Vincent Bernat02779b62016-04-03 13:48:43 +02001402 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001403
Willy Tarreau18324f52014-06-27 18:10:07 +02001404 /* just after the address, a length may be specified */
1405 if (strcmp(args[arg+2], "len") == 0) {
1406 len = atoi(args[arg+3]);
1407 if (len < 80 || len > 65535) {
1408 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1409 file, linenum, args[arg+3]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413 logsrv->maxlen = len;
1414
1415 /* skip these two args */
1416 arg += 2;
1417 }
1418 else
1419 logsrv->maxlen = MAX_SYSLOG_LEN;
1420
1421 if (logsrv->maxlen > global.max_syslog_len) {
1422 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001423 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1424 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1425 logline = my_realloc2(logline, global.max_syslog_len + 1);
1426 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 }
1428
Dragan Dosen1322d092015-09-22 16:05:32 +02001429 /* after the length, a format may be specified */
1430 if (strcmp(args[arg+2], "format") == 0) {
1431 logsrv->format = get_log_format(args[arg+3]);
1432 if (logsrv->format < 0) {
1433 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1434 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001435 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001436 goto out;
1437 }
1438
1439 /* skip these two args */
1440 arg += 2;
1441 }
1442
David Carlier97880bb2016-04-08 10:35:26 +01001443 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1444 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001445 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001446 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001447
Willy Tarreau18324f52014-06-27 18:10:07 +02001448 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001449 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001450 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001451 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001452 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 }
1454
William Lallemand0f99e342011-10-12 17:50:54 +02001455 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001456 if (*(args[arg+3])) {
1457 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001458 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001459 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001461 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
1463 }
1464
William Lallemand0f99e342011-10-12 17:50:54 +02001465 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001466 if (*(args[arg+4])) {
1467 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001468 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001469 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001471 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001472 }
1473 }
1474
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001475 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001476 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001477 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001478 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001479 free(logsrv);
1480 goto out;
1481 }
1482 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001483
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001484 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001485 if (port1 != port2) {
1486 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1487 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001488 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001489 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001490 goto out;
1491 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001492
William Lallemand0f99e342011-10-12 17:50:54 +02001493 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001494 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001495 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497
William Lallemand0f99e342011-10-12 17:50:54 +02001498 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001499 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001500 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1501 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001502
1503 if (global.log_send_hostname != NULL) {
1504 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1505 err_code |= ERR_ALERT;
1506 goto out;
1507 }
1508
1509 if (*(args[1]))
1510 name = args[1];
1511 else
1512 name = hostname;
1513
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001514 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001515 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001516 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001517 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1518 if (global.server_state_base != NULL) {
1519 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1520 err_code |= ERR_ALERT;
1521 goto out;
1522 }
1523
1524 if (!*(args[1])) {
1525 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1526 err_code |= ERR_FATAL;
1527 goto out;
1528 }
1529
1530 global.server_state_base = strdup(args[1]);
1531 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001532 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1533 if (global.server_state_file != NULL) {
1534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1535 err_code |= ERR_ALERT;
1536 goto out;
1537 }
1538
1539 if (!*(args[1])) {
1540 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1541 err_code |= ERR_FATAL;
1542 goto out;
1543 }
1544
1545 global.server_state_file = strdup(args[1]);
1546 }
Kevinm48936af2010-12-22 16:08:21 +00001547 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001548 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1549 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001550 if (*(args[1]) == 0) {
1551 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1552 err_code |= ERR_ALERT | ERR_FATAL;
1553 goto out;
1554 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001555 chunk_destroy(&global.log_tag);
1556 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001557 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001558 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001559 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1560 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001561 if (global.spread_checks != 0) {
1562 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 err_code |= ERR_ALERT;
1564 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001565 }
1566 if (*(args[1]) == 0) {
1567 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001568 err_code |= ERR_ALERT | ERR_FATAL;
1569 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001570 }
1571 global.spread_checks = atol(args[1]);
1572 if (global.spread_checks < 0 || global.spread_checks > 50) {
1573 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001577 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1578 const char *err;
1579 unsigned int val;
1580
William Lallemand1a748ae2015-05-19 16:37:23 +02001581 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1582 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001583 if (*(args[1]) == 0) {
1584 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
1588
1589 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1590 if (err) {
1591 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1592 err_code |= ERR_ALERT | ERR_FATAL;
1593 }
1594 global.max_spread_checks = val;
1595 if (global.max_spread_checks < 0) {
1596 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 }
1599 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001600 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1601#ifdef USE_CPU_AFFINITY
1602 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001603 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001604 unsigned long cpus = 0;
1605
1606 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001607 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001608 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001609 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001610 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001611 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001612 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 proc = atol(args[1]);
1614 if (proc >= 1 && proc <= LONGBITS)
1615 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 }
1617
1618 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001619 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",
1620 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
1625 cur_arg = 2;
1626 while (*args[cur_arg]) {
1627 unsigned int low, high;
1628
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001629 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001630 char *dash = strchr(args[cur_arg], '-');
1631
1632 low = high = str2uic(args[cur_arg]);
1633 if (dash)
1634 high = str2uic(dash + 1);
1635
1636 if (high < low) {
1637 unsigned int swap = low;
1638 low = high;
1639 high = swap;
1640 }
1641
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001642 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001643 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001644 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
1648
1649 while (low <= high)
1650 cpus |= 1UL << low++;
1651 }
1652 else {
1653 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1654 file, linenum, args[0], args[cur_arg]);
1655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
1657 }
1658 cur_arg++;
1659 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001660 for (i = 0; i < LONGBITS; i++)
1661 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001662 global.cpu_map[i] = cpus;
1663#else
1664 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667#endif
1668 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001669 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1670 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1671 goto out;
1672
1673 if (*(args[2]) == 0) {
1674 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
1677 }
1678
1679 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1680 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1681 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
1684 }
1685 }
1686 else if (!strcmp(args[0], "unsetenv")) {
1687 int arg;
1688
1689 if (*(args[1]) == 0) {
1690 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
1693 }
1694
1695 for (arg = 1; *args[arg]; arg++) {
1696 if (unsetenv(args[arg]) != 0) {
1697 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
1700 }
1701 }
1702 }
1703 else if (!strcmp(args[0], "resetenv")) {
1704 extern char **environ;
1705 char **env = environ;
1706
1707 /* args contain variable names to keep, one per argument */
1708 while (*env) {
1709 int arg;
1710
1711 /* look for current variable in among all those we want to keep */
1712 for (arg = 1; *args[arg]; arg++) {
1713 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1714 (*env)[strlen(args[arg])] == '=')
1715 break;
1716 }
1717
1718 /* delete this variable */
1719 if (!*args[arg]) {
1720 char *delim = strchr(*env, '=');
1721
1722 if (!delim || delim - *env >= trash.size) {
1723 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1724 err_code |= ERR_ALERT | ERR_FATAL;
1725 goto out;
1726 }
1727
1728 memcpy(trash.str, *env, delim - *env);
1729 trash.str[delim - *env] = 0;
1730
1731 if (unsetenv(trash.str) != 0) {
1732 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736 }
1737 else
1738 env++;
1739 }
1740 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001742 struct cfg_kw_list *kwl;
1743 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001744 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001745
1746 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1747 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1748 if (kwl->kw[index].section != CFG_GLOBAL)
1749 continue;
1750 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001751 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001752 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001753 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001754 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001755 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001756 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001757 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001758 err_code |= ERR_WARN;
1759 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001760 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001761 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001762 }
1763 }
1764 }
1765
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001769
Willy Tarreau058e9072009-07-20 09:30:05 +02001770 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001771 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773}
1774
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001775void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001777 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 defproxy.mode = PR_MODE_TCP;
1779 defproxy.state = PR_STNEW;
1780 defproxy.maxconn = cfg_maxpconn;
1781 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001782 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001783 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001784
Simon Horman66183002013-02-23 10:16:43 +09001785 defproxy.defsrv.check.inter = DEF_CHKINTR;
1786 defproxy.defsrv.check.fastinter = 0;
1787 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001788 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1789 defproxy.defsrv.agent.fastinter = 0;
1790 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001791 defproxy.defsrv.check.rise = DEF_RISETIME;
1792 defproxy.defsrv.check.fall = DEF_FALLTIME;
1793 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1794 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001795 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001796 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001797 defproxy.defsrv.maxqueue = 0;
1798 defproxy.defsrv.minconn = 0;
1799 defproxy.defsrv.maxconn = 0;
1800 defproxy.defsrv.slowstart = 0;
1801 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1802 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1803 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001804
1805 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001806 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807}
1808
Willy Tarreauade5ec42010-01-28 19:33:49 +01001809
Willy Tarreau63af98d2014-05-18 08:11:41 +02001810/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1811 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1812 * ERR_FATAL in case of error.
1813 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001814static int create_cond_regex_rule(const char *file, int line,
1815 struct proxy *px, int dir, int action, int flags,
1816 const char *cmd, const char *reg, const char *repl,
1817 const char **cond_start)
1818{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001819 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001820 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001821 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001822 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001823 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001824 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001825 int cs;
1826 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001827
1828 if (px == &defproxy) {
1829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001830 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001831 goto err;
1832 }
1833
1834 if (*reg == 0) {
1835 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837 goto err;
1838 }
1839
Christopher Faulet898566e2016-10-26 11:06:28 +02001840 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001841 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001842
Willy Tarreau5321c422010-01-28 20:35:13 +01001843 if (cond_start &&
1844 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001845 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1846 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1847 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001848 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001849 goto err;
1850 }
1851 }
1852 else if (cond_start && **cond_start) {
1853 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1854 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001855 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001856 goto err;
1857 }
1858
Willy Tarreau63af98d2014-05-18 08:11:41 +02001859 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001860 (dir == SMP_OPT_DIR_REQ) ?
1861 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1862 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1863 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001864
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001865 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866 if (!preg) {
1867 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869 goto err;
1870 }
1871
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001872 cs = !(flags & REG_ICASE);
1873 cap = !(flags & REG_NOSUB);
1874 error = NULL;
1875 if (!regex_comp(reg, preg, cs, cap, &error)) {
1876 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1877 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001878 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879 goto err;
1880 }
1881
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001882 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001883 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884 if (repl && err) {
1885 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1886 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 ret_code |= ERR_ALERT | ERR_FATAL;
1888 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889 }
1890
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001891 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001892 ret_code |= ERR_WARN;
1893
1894 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895
Willy Tarreau63af98d2014-05-18 08:11:41 +02001896 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001898 err:
1899 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001900 free(errmsg);
1901 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001902}
1903
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904/*
William Lallemand51097192015-04-14 16:35:22 +02001905 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001906 * Returns the error code, 0 if OK, or any combination of :
1907 * - ERR_ABORT: must abort ASAP
1908 * - ERR_FATAL: we can continue parsing but not start the service
1909 * - ERR_WARN: a warning has been emitted
1910 * - ERR_ALERT: an alert has been emitted
1911 * Only the two first ones can stop processing, the two others are just
1912 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001914int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1915{
1916 static struct peers *curpeers = NULL;
1917 struct peer *newpeer = NULL;
1918 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001919 struct bind_conf *bind_conf;
1920 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001921 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001922 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001923
1924 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001925 if (!*args[1]) {
1926 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001927 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001928 goto out;
1929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001930
William Lallemand6e62fb62015-04-28 16:55:23 +02001931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1932 goto out;
1933
Emeric Brun32da3c42010-09-23 18:39:19 +02001934 err = invalid_char(args[1]);
1935 if (err) {
1936 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1937 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001938 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001939 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001940 }
1941
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001942 for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001943 /*
1944 * If there are two proxies with the same name only following
1945 * combinations are allowed:
1946 */
1947 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001948 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 +02001949 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001951 }
1952 }
1953
Vincent Bernat02779b62016-04-03 13:48:43 +02001954 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001955 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1956 err_code |= ERR_ALERT | ERR_ABORT;
1957 goto out;
1958 }
1959
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02001960 curpeers->next = cfg_peers;
1961 cfg_peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001962 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001963 curpeers->conf.line = linenum;
1964 curpeers->last_change = now.tv_sec;
1965 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001966 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001967 }
1968 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001969 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001970 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001971 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001972
1973 if (!*args[2]) {
1974 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1975 file, linenum, args[0]);
1976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
1978 }
1979
1980 err = invalid_char(args[1]);
1981 if (err) {
1982 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1983 file, linenum, *err, args[1]);
1984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
1986 }
1987
Vincent Bernat02779b62016-04-03 13:48:43 +02001988 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001989 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1990 err_code |= ERR_ALERT | ERR_ABORT;
1991 goto out;
1992 }
1993
1994 /* the peers are linked backwards first */
1995 curpeers->count++;
1996 newpeer->next = curpeers->remote;
1997 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001998 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001999 newpeer->conf.line = linenum;
2000
2001 newpeer->last_change = now.tv_sec;
2002 newpeer->id = strdup(args[1]);
2003
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002004 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002005 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002006 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002010
2011 proto = protocol_by_family(sk->ss_family);
2012 if (!proto || !proto->connect) {
2013 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2014 file, linenum, args[0], args[1]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002018
2019 if (port1 != port2) {
2020 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2021 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
2024 }
2025
Willy Tarreau2aa38802013-02-20 19:20:59 +01002026 if (!port1) {
2027 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2028 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
2031 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002032
Emeric Brun32da3c42010-09-23 18:39:19 +02002033 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002034 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002035 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002036 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002037
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 if (strcmp(newpeer->id, localpeer) == 0) {
2039 /* Current is local peer, it define a frontend */
2040 newpeer->local = 1;
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002041 cfg_peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002042
2043 if (!curpeers->peers_fe) {
2044 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2045 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2046 err_code |= ERR_ALERT | ERR_ABORT;
2047 goto out;
2048 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002049
Willy Tarreau237250c2011-07-29 01:49:03 +02002050 init_new_proxy(curpeers->peers_fe);
2051 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002052 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002053 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2054 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002055 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002056
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002057 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002058
Willy Tarreau902636f2013-03-10 19:44:48 +01002059 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2060 if (errmsg && *errmsg) {
2061 indent_msg(&errmsg, 2);
2062 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002063 }
2064 else
2065 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2066 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002067 err_code |= ERR_FATAL;
2068 goto out;
2069 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002070
2071 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002072 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002073 l->maxconn = curpeers->peers_fe->maxconn;
2074 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002075 l->accept = session_accept_fd;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002076 l->analysers |= curpeers->peers_fe->fe_req_ana;
2077 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002078 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2079 global.maxsock += l->maxconn;
2080 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002081 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002082 else {
2083 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2084 file, linenum, args[0], args[1],
2085 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2086 err_code |= ERR_FATAL;
2087 goto out;
2088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002089 }
2090 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002091 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2092 curpeers->state = PR_STSTOPPED;
2093 }
2094 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2095 curpeers->state = PR_STNEW;
2096 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 else if (*args[0] != 0) {
2098 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
2101 }
2102
2103out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002104 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 return err_code;
2106}
2107
Baptiste Assmann325137d2015-04-13 23:40:55 +02002108/*
2109 * Parse a <resolvers> section.
2110 * Returns the error code, 0 if OK, or any combination of :
2111 * - ERR_ABORT: must abort ASAP
2112 * - ERR_FATAL: we can continue parsing but not start the service
2113 * - ERR_WARN: a warning has been emitted
2114 * - ERR_ALERT: an alert has been emitted
2115 * Only the two first ones can stop processing, the two others are just
2116 * indicators.
2117 */
2118int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2119{
2120 static struct dns_resolvers *curr_resolvers = NULL;
2121 struct dns_nameserver *newnameserver = NULL;
2122 const char *err;
2123 int err_code = 0;
2124 char *errmsg = NULL;
2125
2126 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2127 if (!*args[1]) {
2128 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2129 err_code |= ERR_ALERT | ERR_ABORT;
2130 goto out;
2131 }
2132
2133 err = invalid_char(args[1]);
2134 if (err) {
2135 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2136 file, linenum, *err, args[0], args[1]);
2137 err_code |= ERR_ALERT | ERR_ABORT;
2138 goto out;
2139 }
2140
2141 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2142 /* Error if two resolvers owns the same name */
2143 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2144 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2145 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2146 err_code |= ERR_ALERT | ERR_ABORT;
2147 }
2148 }
2149
Vincent Bernat02779b62016-04-03 13:48:43 +02002150 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002151 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2152 err_code |= ERR_ALERT | ERR_ABORT;
2153 goto out;
2154 }
2155
2156 /* default values */
2157 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2158 curr_resolvers->conf.file = strdup(file);
2159 curr_resolvers->conf.line = linenum;
2160 curr_resolvers->id = strdup(args[1]);
2161 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002162 /* default maximum response size */
2163 curr_resolvers->accepted_payload_size = 512;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002164 /* default hold period for nx, other, refuse and timeout is 30s */
2165 curr_resolvers->hold.nx = 30000;
2166 curr_resolvers->hold.other = 30000;
2167 curr_resolvers->hold.refused = 30000;
2168 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann686408b2017-08-18 10:15:42 +02002169 curr_resolvers->hold.obsolete = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002170 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002171 curr_resolvers->hold.valid = 10000;
2172 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002173 curr_resolvers->resolve_retries = 3;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002174 /* default resolution pool size */
2175 curr_resolvers->resolution_pool_size = DNS_DEFAULT_RESOLUTION_POOL_SIZE;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 LIST_INIT(&curr_resolvers->nameserver_list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002177 LIST_INIT(&curr_resolvers->resolution.curr);
2178 LIST_INIT(&curr_resolvers->resolution.wait);
2179 LIST_INIT(&curr_resolvers->resolution.pool);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002180 }
2181 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2182 struct sockaddr_storage *sk;
2183 int port1, port2;
2184 struct protocol *proto;
2185
2186 if (!*args[2]) {
2187 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2188 file, linenum, args[0]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
2193 err = invalid_char(args[1]);
2194 if (err) {
2195 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2196 file, linenum, *err, args[1]);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
Baptiste Assmanna315c552015-11-02 22:55:49 +01002201 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2202 /* Error if two resolvers owns the same name */
2203 if (strcmp(newnameserver->id, args[1]) == 0) {
2204 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2205 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 }
2208 }
2209
Vincent Bernat02779b62016-04-03 13:48:43 +02002210 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2212 err_code |= ERR_ALERT | ERR_ABORT;
2213 goto out;
2214 }
2215
2216 /* the nameservers are linked backward first */
2217 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2218 curr_resolvers->count_nameservers++;
2219 newnameserver->resolvers = curr_resolvers;
2220 newnameserver->conf.file = strdup(file);
2221 newnameserver->conf.line = linenum;
2222 newnameserver->id = strdup(args[1]);
2223
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002224 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002225 if (!sk) {
2226 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
2229 }
2230
2231 proto = protocol_by_family(sk->ss_family);
2232 if (!proto || !proto->connect) {
2233 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2234 file, linenum, args[0], args[1]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
2238
2239 if (port1 != port2) {
2240 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2241 file, linenum, args[0], args[1], args[2]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002246 if (!port1 && !port2) {
2247 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2248 file, linenum, args[0], args[1]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252
Baptiste Assmann325137d2015-04-13 23:40:55 +02002253 newnameserver->addr = *sk;
2254 }
2255 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2256 const char *res;
2257 unsigned int time;
2258
2259 if (!*args[2]) {
2260 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2261 file, linenum, args[0]);
2262 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
2265 }
2266 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2267 if (res) {
2268 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2269 file, linenum, *res, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002273 if (strcmp(args[1], "nx") == 0)
2274 curr_resolvers->hold.nx = time;
2275 else if (strcmp(args[1], "other") == 0)
2276 curr_resolvers->hold.other = time;
2277 else if (strcmp(args[1], "refused") == 0)
2278 curr_resolvers->hold.refused = time;
2279 else if (strcmp(args[1], "timeout") == 0)
2280 curr_resolvers->hold.timeout = time;
2281 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002282 curr_resolvers->hold.valid = time;
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002283 else if (strcmp(args[1], "obsolete") == 0)
2284 curr_resolvers->hold.obsolete = time;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002285 else {
Olivier Houcharda8c6db82017-07-06 18:46:47 +02002286 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', 'obsolete' or 'other'.\n",
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002287 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
2292 }
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002293 else if (strcmp(args[0], "accepted_payload_size") == 0) {
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002294 int i = 0;
2295
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002296 if (!*args[1]) {
2297 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2298 file, linenum, args[0]);
2299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002302
2303 i = atoi(args[1]);
Willy Tarreau0c219be2017-08-22 12:01:26 +02002304 if (i < DNS_HEADER_SIZE || i > DNS_MAX_UDP_MESSAGE) {
2305 Alert("parsing [%s:%d] : '%s' must be between %d and %d inclusive (was %s).\n",
2306 file, linenum, args[0], DNS_HEADER_SIZE, DNS_MAX_UDP_MESSAGE, args[1]);
Baptiste Assmann9d8dbbc2017-08-18 23:35:08 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310
2311 curr_resolvers->accepted_payload_size = i;
Baptiste Assmann2af08fe2017-08-14 00:13:01 +02002312 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002313 else if (strcmp(args[0], "resolution_pool_size") == 0) {
2314 if (!*args[1]) {
2315 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2316 file, linenum, args[0]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320 curr_resolvers->resolution_pool_size = atoi(args[1]);
2321 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002322 else if (strcmp(args[0], "resolve_retries") == 0) {
2323 if (!*args[1]) {
2324 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2325 file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329 curr_resolvers->resolve_retries = atoi(args[1]);
2330 }
2331 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002332 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002333 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2334 file, linenum, args[0]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002338 else if (strcmp(args[1], "retry") == 0) {
2339 const char *res;
2340 unsigned int timeout_retry;
2341
2342 if (!*args[2]) {
2343 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2344 file, linenum, args[0], args[1]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2349 if (res) {
2350 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2351 file, linenum, *res, args[0], args[1]);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355 curr_resolvers->timeout.retry = timeout_retry;
2356 }
2357 else {
2358 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2359 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
2362 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002363 } /* neither "nameserver" nor "resolvers" */
2364 else if (*args[0] != 0) {
2365 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369
2370 out:
2371 free(errmsg);
2372 return err_code;
2373}
Simon Horman0d16a402015-01-30 11:22:58 +09002374
2375/*
William Lallemand51097192015-04-14 16:35:22 +02002376 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002377 * Returns the error code, 0 if OK, or any combination of :
2378 * - ERR_ABORT: must abort ASAP
2379 * - ERR_FATAL: we can continue parsing but not start the service
2380 * - ERR_WARN: a warning has been emitted
2381 * - ERR_ALERT: an alert has been emitted
2382 * Only the two first ones can stop processing, the two others are just
2383 * indicators.
2384 */
2385int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2386{
2387 static struct mailers *curmailers = NULL;
2388 struct mailer *newmailer = NULL;
2389 const char *err;
2390 int err_code = 0;
2391 char *errmsg = NULL;
2392
2393 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2394 if (!*args[1]) {
2395 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2396 err_code |= ERR_ALERT | ERR_ABORT;
2397 goto out;
2398 }
2399
2400 err = invalid_char(args[1]);
2401 if (err) {
2402 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2403 file, linenum, *err, args[0], args[1]);
2404 err_code |= ERR_ALERT | ERR_ABORT;
2405 goto out;
2406 }
2407
2408 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2409 /*
2410 * If there are two proxies with the same name only following
2411 * combinations are allowed:
2412 */
2413 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002414 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 +09002415 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002417 }
2418 }
2419
Vincent Bernat02779b62016-04-03 13:48:43 +02002420 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002421 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2422 err_code |= ERR_ALERT | ERR_ABORT;
2423 goto out;
2424 }
2425
2426 curmailers->next = mailers;
2427 mailers = curmailers;
2428 curmailers->conf.file = strdup(file);
2429 curmailers->conf.line = linenum;
2430 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002431 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2432 * But need enough time so that timeouts don't occur
2433 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002434 }
2435 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2436 struct sockaddr_storage *sk;
2437 int port1, port2;
2438 struct protocol *proto;
2439
2440 if (!*args[2]) {
2441 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2442 file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
2447 err = invalid_char(args[1]);
2448 if (err) {
2449 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2450 file, linenum, *err, args[1]);
2451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
2453 }
2454
Vincent Bernat02779b62016-04-03 13:48:43 +02002455 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2457 err_code |= ERR_ALERT | ERR_ABORT;
2458 goto out;
2459 }
2460
2461 /* the mailers are linked backwards first */
2462 curmailers->count++;
2463 newmailer->next = curmailers->mailer_list;
2464 curmailers->mailer_list = newmailer;
2465 newmailer->mailers = curmailers;
2466 newmailer->conf.file = strdup(file);
2467 newmailer->conf.line = linenum;
2468
2469 newmailer->id = strdup(args[1]);
2470
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002471 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002472 if (!sk) {
2473 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
2476 }
2477
2478 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002479 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2480 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002481 file, linenum, args[0], args[1]);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486 if (port1 != port2) {
2487 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2488 file, linenum, args[0], args[1], args[2]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493 if (!port1) {
2494 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2495 file, linenum, args[0], args[1], args[2]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499
2500 newmailer->addr = *sk;
2501 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002502 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002503 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002504 }
2505 else if (strcmp(args[0], "timeout") == 0) {
2506 if (!*args[1]) {
2507 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2508 file, linenum, args[0]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512 else if (strcmp(args[1], "mail") == 0) {
2513 const char *res;
2514 unsigned int timeout_mail;
2515 if (!*args[2]) {
2516 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2517 file, linenum, args[0], args[1]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2522 if (res) {
2523 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2524 file, linenum, *res, args[0]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528 if (timeout_mail <= 0) {
2529 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533 curmailers->timeout.mail = timeout_mail;
2534 } else {
2535 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2536 file, linenum, args[0], args[1]);
2537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
2539 }
2540 }
Simon Horman0d16a402015-01-30 11:22:58 +09002541 else if (*args[0] != 0) {
2542 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546
2547out:
2548 free(errmsg);
2549 return err_code;
2550}
2551
Simon Horman9dc49962015-01-30 11:22:59 +09002552static void free_email_alert(struct proxy *p)
2553{
2554 free(p->email_alert.mailers.name);
2555 p->email_alert.mailers.name = NULL;
2556 free(p->email_alert.from);
2557 p->email_alert.from = NULL;
2558 free(p->email_alert.to);
2559 p->email_alert.to = NULL;
2560 free(p->email_alert.myhostname);
2561 p->email_alert.myhostname = NULL;
2562}
2563
Willy Tarreau3842f002009-06-14 11:39:52 +02002564int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565{
2566 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002567 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002568 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002569 int rc;
2570 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002571 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002572 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002573 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002574 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002575 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 if (!strcmp(args[0], "listen"))
2578 rc = PR_CAP_LISTEN;
2579 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002580 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002581 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002582 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 else
2584 rc = PR_CAP_NONE;
2585
2586 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 if (!*args[1]) {
2588 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002589 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_ABORT;
2592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002594
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002595 err = invalid_char(args[1]);
2596 if (err) {
2597 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2598 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002600 }
2601
Willy Tarreau8f50b682015-05-26 11:45:02 +02002602 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2603 if (curproxy) {
2604 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2605 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2606 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002608 }
2609
Vincent Bernat02779b62016-04-03 13:48:43 +02002610 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_ABORT;
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002615
Willy Tarreau97cb7802010-01-03 20:23:58 +01002616 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->next = proxy;
2618 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002619 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2620 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002621 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002624 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625
William Lallemand6e62fb62015-04-28 16:55:23 +02002626 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2627 if (curproxy->cap & PR_CAP_FE)
2628 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 }
2631
2632 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002633 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002634 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002635
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002638 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002639 curproxy->no_options = defproxy.no_options;
2640 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002641 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002642 curproxy->except_net = defproxy.except_net;
2643 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002644 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002645 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002647 if (defproxy.fwdfor_hdr_len) {
2648 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2649 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2650 }
2651
Willy Tarreaub86db342009-11-30 11:50:16 +01002652 if (defproxy.orgto_hdr_len) {
2653 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2654 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2655 }
2656
Mark Lamourinec2247f02012-01-04 13:02:01 -05002657 if (defproxy.server_id_hdr_len) {
2658 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2659 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2660 }
2661
Willy Tarreau977b8e42006-12-29 14:19:17 +01002662 if (curproxy->cap & PR_CAP_FE) {
2663 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002664 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002665 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666
2667 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002668 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2669 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670
2671 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673
Willy Tarreau977b8e42006-12-29 14:19:17 +01002674 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002675 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002676 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 curproxy->fullconn = defproxy.fullconn;
2678 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002679 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002680 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002682 if (defproxy.check_req) {
2683 curproxy->check_req = calloc(1, defproxy.check_len);
2684 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002686 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002688 if (defproxy.expect_str) {
2689 curproxy->expect_str = strdup(defproxy.expect_str);
2690 if (defproxy.expect_regex) {
2691 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002692 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2693 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002694 }
2695 }
2696
Willy Tarreau67402132012-05-31 20:40:20 +02002697 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 if (defproxy.cookie_name)
2699 curproxy->cookie_name = strdup(defproxy.cookie_name);
2700 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002701
2702 if (defproxy.dyncookie_key)
2703 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002704 if (defproxy.cookie_domain)
2705 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002706
Willy Tarreau31936852010-10-06 16:59:56 +02002707 if (defproxy.cookie_maxidle)
2708 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2709
2710 if (defproxy.cookie_maxlife)
2711 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2712
Emeric Brun647caf12009-06-30 17:57:00 +02002713 if (defproxy.rdp_cookie_name)
2714 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2715 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2716
Willy Tarreau01732802007-11-01 22:48:15 +01002717 if (defproxy.url_param_name)
2718 curproxy->url_param_name = strdup(defproxy.url_param_name);
2719 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002720
Benoitaffb4812009-03-25 13:02:10 +01002721 if (defproxy.hh_name)
2722 curproxy->hh_name = strdup(defproxy.hh_name);
2723 curproxy->hh_len = defproxy.hh_len;
2724 curproxy->hh_match_domain = defproxy.hh_match_domain;
2725
Willy Tarreauef9a3602012-12-08 22:29:20 +01002726 if (defproxy.conn_src.iface_name)
2727 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2728 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002729 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002730#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002731 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002732#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002733 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002736 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737 if (defproxy.capture_name)
2738 curproxy->capture_name = strdup(defproxy.capture_name);
2739 curproxy->capture_namelen = defproxy.capture_namelen;
2740 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002744 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002745 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002746 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002747 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002748 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 curproxy->mon_net = defproxy.mon_net;
2750 curproxy->mon_mask = defproxy.mon_mask;
2751 if (defproxy.monitor_uri)
2752 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2753 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002754 if (defproxy.defbe.name)
2755 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002756
2757 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002758 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2759 if (curproxy->conf.logformat_string &&
2760 curproxy->conf.logformat_string != default_http_log_format &&
2761 curproxy->conf.logformat_string != default_tcp_log_format &&
2762 curproxy->conf.logformat_string != clf_http_log_format)
2763 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2764
2765 if (defproxy.conf.lfs_file) {
2766 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2767 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2768 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002769
2770 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2771 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2772 if (curproxy->conf.logformat_sd_string &&
2773 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2774 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2775
2776 if (defproxy.conf.lfsd_file) {
2777 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2778 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2779 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 }
2781
2782 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002783 curproxy->timeout.connect = defproxy.timeout.connect;
2784 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002785 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002786 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002787 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002788 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002789 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002790 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002791 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002792 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002793 }
2794
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002796 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002797
2798 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002799 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002800 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002801 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002802 LIST_INIT(&node->list);
2803 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2804 }
2805
Willy Tarreau62a61232013-04-12 18:13:46 +02002806 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2807 if (curproxy->conf.uniqueid_format_string)
2808 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2809
Dragan Dosen43885c72015-10-01 13:18:13 +02002810 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002811
Willy Tarreau62a61232013-04-12 18:13:46 +02002812 if (defproxy.conf.uif_file) {
2813 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2814 curproxy->conf.uif_line = defproxy.conf.uif_line;
2815 }
William Lallemanda73203e2012-03-12 12:48:57 +01002816
2817 /* copy default header unique id */
2818 if (defproxy.header_unique_id)
2819 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2820
William Lallemand82fe75c2012-10-23 10:25:10 +02002821 /* default compression options */
2822 if (defproxy.comp != NULL) {
2823 curproxy->comp = calloc(1, sizeof(struct comp));
2824 curproxy->comp->algos = defproxy.comp->algos;
2825 curproxy->comp->types = defproxy.comp->types;
2826 }
2827
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002829 curproxy->conf.used_listener_id = EB_ROOT;
2830 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002831
Simon Horman98637e52014-06-20 12:30:16 +09002832 if (defproxy.check_path)
2833 curproxy->check_path = strdup(defproxy.check_path);
2834 if (defproxy.check_command)
2835 curproxy->check_command = strdup(defproxy.check_command);
2836
Simon Horman9dc49962015-01-30 11:22:59 +09002837 if (defproxy.email_alert.mailers.name)
2838 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2839 if (defproxy.email_alert.from)
2840 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2841 if (defproxy.email_alert.to)
2842 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2843 if (defproxy.email_alert.myhostname)
2844 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002845 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002846 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002847
Willy Tarreau93893792009-07-23 13:19:11 +02002848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
2850 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2851 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002852 /* FIXME-20070101: we should do this too at the end of the
2853 * config parsing to free all default values.
2854 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002855 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2856 err_code |= ERR_ABORT;
2857 goto out;
2858 }
2859
Willy Tarreaua534fea2008-08-03 12:19:50 +02002860 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002861 free(defproxy.check_command);
2862 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002863 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002864 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002865 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002866 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002867 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002868 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002869 free(defproxy.capture_name);
2870 free(defproxy.monitor_uri);
2871 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002872 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002873 free(defproxy.fwdfor_hdr_name);
2874 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002875 free(defproxy.orgto_hdr_name);
2876 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002877 free(defproxy.server_id_hdr_name);
2878 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002879 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002880 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002881 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002882 free(defproxy.expect_regex);
2883 defproxy.expect_regex = NULL;
2884 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002885
Willy Tarreau62a61232013-04-12 18:13:46 +02002886 if (defproxy.conf.logformat_string != default_http_log_format &&
2887 defproxy.conf.logformat_string != default_tcp_log_format &&
2888 defproxy.conf.logformat_string != clf_http_log_format)
2889 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002890
Willy Tarreau62a61232013-04-12 18:13:46 +02002891 free(defproxy.conf.uniqueid_format_string);
2892 free(defproxy.conf.lfs_file);
2893 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002894 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002895 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002896
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002897 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2898 free(defproxy.conf.logformat_sd_string);
2899 free(defproxy.conf.lfsd_file);
2900
Willy Tarreaua534fea2008-08-03 12:19:50 +02002901 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002902 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002903
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 /* we cannot free uri_auth because it might already be used */
2905 init_default_instance();
2906 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002907 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2908 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002909 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
2912 else if (curproxy == NULL) {
2913 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002917
2918 /* update the current file and line being parsed */
2919 curproxy->conf.args.file = curproxy->conf.file;
2920 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921
2922 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002923 if (!strcmp(args[0], "server") ||
2924 !strcmp(args[0], "default-server") ||
2925 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002926 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2927 if (err_code & ERR_FATAL)
2928 goto out;
2929 }
2930 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002931 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002932 int cur_arg;
2933
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 if (curproxy == &defproxy) {
2935 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002939 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941
Willy Tarreau24709282013-03-10 21:32:12 +01002942 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002943 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002948
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002949 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002950
2951 /* use default settings for unix sockets */
2952 bind_conf->ux.uid = global.unix_bind.ux.uid;
2953 bind_conf->ux.gid = global.unix_bind.ux.gid;
2954 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002955
2956 /* NOTE: the following line might create several listeners if there
2957 * are comma-separated IPs or port ranges. So all further processing
2958 * will have to be applied to all listeners created after last_listen.
2959 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002960 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2961 if (errmsg && *errmsg) {
2962 indent_msg(&errmsg, 2);
2963 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002964 }
2965 else
2966 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2967 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002971
Willy Tarreau4348fad2012-09-20 16:48:07 +02002972 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2973 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002974 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002975 }
2976
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002977 cur_arg = 2;
2978 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002979 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002980 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002981 char *err;
2982
Willy Tarreau26982662012-09-12 23:17:10 +02002983 kw = bind_find_kw(args[cur_arg]);
2984 if (kw) {
2985 char *err = NULL;
2986 int code;
2987
2988 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002989 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2990 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002991 cur_arg += 1 + kw->skip ;
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
Willy Tarreau4348fad2012-09-20 16:48:07 +02002996 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002997 err_code |= code;
2998
2999 if (code) {
3000 if (err && *err) {
3001 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003002 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003003 }
3004 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003005 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3006 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003007 if (code & ERR_FATAL) {
3008 free(err);
3009 cur_arg += 1 + kw->skip;
3010 goto out;
3011 }
3012 }
3013 free(err);
3014 cur_arg += 1 + kw->skip;
3015 continue;
3016 }
3017
Willy Tarreau8638f482012-09-18 18:01:17 +02003018 err = NULL;
3019 if (!bind_dumped) {
3020 bind_dump_kws(&err);
3021 indent_msg(&err, 4);
3022 bind_dumped = 1;
3023 }
3024
3025 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3026 file, linenum, args[0], args[1], args[cur_arg],
3027 err ? " Registered keywords :" : "", err ? err : "");
3028 free(err);
3029
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003032 }
Willy Tarreau93893792009-07-23 13:19:11 +02003033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 }
3035 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003036 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
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
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 /* flush useless bits */
3046 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003049 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003050 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003052
William Lallemanddf1425a2015-04-28 20:17:49 +02003053 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3054 goto out;
3055
Willy Tarreau1c47f852006-07-09 08:22:27 +02003056 if (!*args[1]) {
3057 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003061 }
3062
Willy Tarreaua534fea2008-08-03 12:19:50 +02003063 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003064 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003065 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003066 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003067 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3068
Willy Tarreau93893792009-07-23 13:19:11 +02003069 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003072 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3073 goto out;
3074
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3076 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3077 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3078 else {
3079 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
3083 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003084 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003085 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003086
3087 if (curproxy == &defproxy) {
3088 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3089 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003092 }
3093
William Lallemanddf1425a2015-04-28 20:17:49 +02003094 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3095 goto out;
3096
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003097 if (!*args[1]) {
3098 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003102 }
3103
3104 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003105 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003106 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003107
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003108 if (curproxy->uuid <= 0) {
3109 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003110 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003113 }
3114
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003115 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3116 if (node) {
3117 struct proxy *target = container_of(node, struct proxy, conf.id);
3118 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3119 file, linenum, proxy_type_str(curproxy), curproxy->id,
3120 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003125 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003126 else if (!strcmp(args[0], "description")) {
3127 int i, len=0;
3128 char *d;
3129
Cyril Bonté99ed3272010-01-24 23:29:44 +01003130 if (curproxy == &defproxy) {
3131 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3132 file, linenum, args[0]);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
3136
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003137 if (!*args[1]) {
3138 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3139 file, linenum, args[0]);
3140 return -1;
3141 }
3142
Willy Tarreau348acfe2014-04-14 15:00:39 +02003143 for (i = 1; *args[i]; i++)
3144 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003145
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003146 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003147 curproxy->desc = d;
3148
Willy Tarreau348acfe2014-04-14 15:00:39 +02003149 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3150 for (i = 2; *args[i]; i++)
3151 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003152
3153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003155 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 curproxy->state = PR_STSTOPPED;
3158 }
3159 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003160 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 curproxy->state = PR_STNEW;
3163 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003164 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3165 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003166 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003167
3168 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003169 unsigned int low, high;
3170
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003171 if (strcmp(args[cur_arg], "all") == 0) {
3172 set = 0;
3173 break;
3174 }
3175 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003176 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003177 }
3178 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003179 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003180 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003181 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003182 char *dash = strchr(args[cur_arg], '-');
3183
3184 low = high = str2uic(args[cur_arg]);
3185 if (dash)
3186 high = str2uic(dash + 1);
3187
3188 if (high < low) {
3189 unsigned int swap = low;
3190 low = high;
3191 high = swap;
3192 }
3193
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003194 if (low < 1 || high > LONGBITS) {
3195 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3196 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003199 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003200 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003201 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003202 }
3203 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003204 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3205 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003208 }
3209 cur_arg++;
3210 }
3211 curproxy->bind_proc = set;
3212 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003213 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003214 if (curproxy == &defproxy) {
3215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003218 }
3219
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003220 err = invalid_char(args[1]);
3221 if (err) {
3222 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3223 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003225 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003226 }
3227
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003228 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003229 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3230 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003233 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003234 }
3235 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3236
3237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3238 err_code |= ERR_WARN;
3239
3240 if (*(args[1]) == 0) {
3241 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3242 file, linenum, args[0]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
3246 free(curproxy->dyncookie_key);
3247 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3250 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251
Willy Tarreau977b8e42006-12-29 14:19:17 +01003252 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003254
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 if (*(args[1]) == 0) {
3256 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3257 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003261
Willy Tarreau67402132012-05-31 20:40:20 +02003262 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003263 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003264 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003265 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 curproxy->cookie_name = strdup(args[1]);
3267 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003268
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 cur_arg = 2;
3270 while (*(args[cur_arg])) {
3271 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003272 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
3274 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003275 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003278 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
3280 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003281 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003284 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003286 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003287 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003290 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003292 else if (!strcmp(args[cur_arg], "httponly")) {
3293 curproxy->ck_opts |= PR_CK_HTTPONLY;
3294 }
3295 else if (!strcmp(args[cur_arg], "secure")) {
3296 curproxy->ck_opts |= PR_CK_SECURE;
3297 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003298 else if (!strcmp(args[cur_arg], "domain")) {
3299 if (!*args[cur_arg + 1]) {
3300 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3301 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003304 }
3305
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003306 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003307 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003308 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3309 " dots nor does not start with a dot."
3310 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003311 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003312 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003313 }
3314
3315 err = invalid_domainchar(args[cur_arg + 1]);
3316 if (err) {
3317 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3318 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003321 }
3322
Willy Tarreau68a897b2009-12-03 23:28:34 +01003323 if (!curproxy->cookie_domain) {
3324 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3325 } else {
3326 /* one domain was already specified, add another one by
3327 * building the string which will be returned along with
3328 * the cookie.
3329 */
3330 char *new_ptr;
3331 int new_len = strlen(curproxy->cookie_domain) +
3332 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3333 new_ptr = malloc(new_len);
3334 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3335 free(curproxy->cookie_domain);
3336 curproxy->cookie_domain = new_ptr;
3337 }
Willy Tarreau31936852010-10-06 16:59:56 +02003338 cur_arg++;
3339 }
3340 else if (!strcmp(args[cur_arg], "maxidle")) {
3341 unsigned int maxidle;
3342 const char *res;
3343
3344 if (!*args[cur_arg + 1]) {
3345 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3346 file, linenum, args[cur_arg]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3352 if (res) {
3353 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3354 file, linenum, *res, args[cur_arg]);
3355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
3357 }
3358 curproxy->cookie_maxidle = maxidle;
3359 cur_arg++;
3360 }
3361 else if (!strcmp(args[cur_arg], "maxlife")) {
3362 unsigned int maxlife;
3363 const char *res;
3364
3365 if (!*args[cur_arg + 1]) {
3366 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3367 file, linenum, args[cur_arg]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371
3372 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3373 if (res) {
3374 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3375 file, linenum, *res, args[cur_arg]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
3379 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003380 cur_arg++;
3381 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003382 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003383
3384 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3385 err_code |= ERR_WARN;
3386 curproxy->ck_opts |= PR_CK_DYNAMIC;
3387 }
3388
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003390 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 +02003391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
3395 cur_arg++;
3396 }
Willy Tarreau67402132012-05-31 20:40:20 +02003397 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3399 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
3402
Willy Tarreau67402132012-05-31 20:40:20 +02003403 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3405 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003408
Willy Tarreau67402132012-05-31 20:40:20 +02003409 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003410 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3411 file, linenum);
3412 err_code |= ERR_ALERT | ERR_FATAL;
3413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003415 else if (!strcmp(args[0], "email-alert")) {
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[0]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422
3423 if (!strcmp(args[1], "from")) {
3424 if (*(args[1]) == 0) {
3425 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3426 file, linenum, args[1]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430 free(curproxy->email_alert.from);
3431 curproxy->email_alert.from = strdup(args[2]);
3432 }
3433 else if (!strcmp(args[1], "mailers")) {
3434 if (*(args[1]) == 0) {
3435 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3436 file, linenum, args[1]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440 free(curproxy->email_alert.mailers.name);
3441 curproxy->email_alert.mailers.name = strdup(args[2]);
3442 }
3443 else if (!strcmp(args[1], "myhostname")) {
3444 if (*(args[1]) == 0) {
3445 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3446 file, linenum, args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
3450 free(curproxy->email_alert.myhostname);
3451 curproxy->email_alert.myhostname = strdup(args[2]);
3452 }
Simon Horman64e34162015-02-06 11:11:57 +09003453 else if (!strcmp(args[1], "level")) {
3454 curproxy->email_alert.level = get_log_level(args[2]);
3455 if (curproxy->email_alert.level < 0) {
3456 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3457 file, linenum, args[1], args[2]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461 }
Simon Horman9dc49962015-01-30 11:22:59 +09003462 else if (!strcmp(args[1], "to")) {
3463 if (*(args[1]) == 0) {
3464 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3465 file, linenum, args[1]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469 free(curproxy->email_alert.to);
3470 curproxy->email_alert.to = strdup(args[2]);
3471 }
3472 else {
3473 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3474 file, linenum, args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
Simon Horman64e34162015-02-06 11:11:57 +09003478 /* Indicate that the email_alert is at least partially configured */
3479 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003480 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003481 else if (!strcmp(args[0], "external-check")) {
3482 if (*(args[1]) == 0) {
3483 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3484 file, linenum, args[0]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488
3489 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003490 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003491 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003492 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003493 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3494 file, linenum, args[1]);
3495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
3497 }
3498 free(curproxy->check_command);
3499 curproxy->check_command = strdup(args[2]);
3500 }
3501 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003502 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003503 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003504 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003505 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3506 file, linenum, args[1]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510 free(curproxy->check_path);
3511 curproxy->check_path = strdup(args[2]);
3512 }
3513 else {
3514 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3515 file, linenum, args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003520 else if (!strcmp(args[0], "persist")) { /* persist */
3521 if (*(args[1]) == 0) {
3522 Alert("parsing [%s:%d] : missing persist method.\n",
3523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003526 }
3527
3528 if (!strncmp(args[1], "rdp-cookie", 10)) {
3529 curproxy->options2 |= PR_O2_RDPC_PRST;
3530
Emeric Brunb982a3d2010-01-04 15:45:53 +01003531 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003532 const char *beg, *end;
3533
3534 beg = args[1] + 11;
3535 end = strchr(beg, ')');
3536
William Lallemanddf1425a2015-04-28 20:17:49 +02003537 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3538 goto out;
3539
Emeric Brun647caf12009-06-30 17:57:00 +02003540 if (!end || end == beg) {
3541 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3542 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003545 }
3546
3547 free(curproxy->rdp_cookie_name);
3548 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3549 curproxy->rdp_cookie_len = end-beg;
3550 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003551 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003552 free(curproxy->rdp_cookie_name);
3553 curproxy->rdp_cookie_name = strdup("msts");
3554 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3555 }
3556 else { /* syntax */
3557 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3558 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003561 }
3562 }
3563 else {
3564 Alert("parsing [%s:%d] : unknown persist method.\n",
3565 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003568 }
3569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003571 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
3574 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003575 else if (!strcmp(args[0], "load-server-state-from-file")) {
3576 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3577 err_code |= ERR_WARN;
3578 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3579 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3580 }
3581 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3582 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3583 }
3584 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3585 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3586 }
3587 else {
3588 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3589 file, linenum, args[0], args[1]);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
3592 }
3593 }
3594 else if (!strcmp(args[0], "server-state-file-name")) {
3595 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3596 err_code |= ERR_WARN;
3597 if (*(args[1]) == 0) {
3598 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3599 file, linenum, args[0]);
3600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
3602 }
3603 else if (!strcmp(args[1], "use-backend-name"))
3604 curproxy->server_state_file_name = strdup(curproxy->id);
3605 else
3606 curproxy->server_state_file_name = strdup(args[1]);
3607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003609 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003611
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003613 if (curproxy == &defproxy) {
3614 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
3618
William Lallemand1a748ae2015-05-19 16:37:23 +02003619 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3620 goto out;
3621
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 if (*(args[4]) == 0) {
3623 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3624 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003628 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 curproxy->capture_name = strdup(args[2]);
3630 curproxy->capture_namelen = strlen(curproxy->capture_name);
3631 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 curproxy->to_log |= LW_COOKIE;
3633 }
3634 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3635 struct cap_hdr *hdr;
3636
3637 if (curproxy == &defproxy) {
3638 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 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
3642
William Lallemand1a748ae2015-05-19 16:37:23 +02003643 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3644 goto out;
3645
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3647 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3648 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652
Vincent Bernat02779b62016-04-03 13:48:43 +02003653 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 hdr->next = curproxy->req_cap;
3655 hdr->name = strdup(args[3]);
3656 hdr->namelen = strlen(args[3]);
3657 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003658 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 hdr->index = curproxy->nb_req_cap++;
3660 curproxy->req_cap = hdr;
3661 curproxy->to_log |= LW_REQHDR;
3662 }
3663 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3664 struct cap_hdr *hdr;
3665
3666 if (curproxy == &defproxy) {
3667 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 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
3671
William Lallemand1a748ae2015-05-19 16:37:23 +02003672 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3673 goto out;
3674
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3676 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3677 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003680 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003681 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 hdr->next = curproxy->rsp_cap;
3683 hdr->name = strdup(args[3]);
3684 hdr->namelen = strlen(args[3]);
3685 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003686 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 hdr->index = curproxy->nb_rsp_cap++;
3688 curproxy->rsp_cap = hdr;
3689 curproxy->to_log |= LW_RSPHDR;
3690 }
3691 else {
3692 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 }
3697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003699 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003701
William Lallemanddf1425a2015-04-28 20:17:49 +02003702 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3703 goto out;
3704
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 if (*(args[1]) == 0) {
3706 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711 curproxy->conn_retries = atol(args[1]);
3712 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003713 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003714 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003715
3716 if (curproxy == &defproxy) {
3717 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721
Willy Tarreau20b0de52012-12-24 15:45:22 +01003722 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003723 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003724 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3725 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3726 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3727 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003728 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 +01003729 file, linenum, args[0]);
3730 err_code |= ERR_WARN;
3731 }
3732
Willy Tarreauff011f22011-01-06 17:51:27 +01003733 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003734
Willy Tarreauff011f22011-01-06 17:51:27 +01003735 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003736 err_code |= ERR_ALERT | ERR_ABORT;
3737 goto out;
3738 }
3739
Willy Tarreau5002f572014-04-23 01:32:02 +02003740 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003741 err_code |= warnif_cond_conflicts(rule->cond,
3742 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3743 file, linenum);
3744
Willy Tarreauff011f22011-01-06 17:51:27 +01003745 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003746 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003747 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003748 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003749
3750 if (curproxy == &defproxy) {
3751 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
3754 }
3755
3756 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003757 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003758 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3759 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003760 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3761 file, linenum, args[0]);
3762 err_code |= ERR_WARN;
3763 }
3764
3765 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3766
3767 if (!rule) {
3768 err_code |= ERR_ALERT | ERR_ABORT;
3769 goto out;
3770 }
3771
3772 err_code |= warnif_cond_conflicts(rule->cond,
3773 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3774 file, linenum);
3775
3776 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3777 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003778 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3779 /* set the header name and length into the proxy structure */
3780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3781 err_code |= ERR_WARN;
3782
3783 if (!*args[1]) {
3784 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3785 file, linenum, args[0]);
3786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
3788 }
3789
3790 /* set the desired header name */
3791 free(curproxy->server_id_hdr_name);
3792 curproxy->server_id_hdr_name = strdup(args[1]);
3793 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3794 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003795 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003796 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003797
Willy Tarreaub099aca2008-10-12 17:26:37 +02003798 if (curproxy == &defproxy) {
3799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003802 }
3803
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003804 /* emulate "block" using "http-request block". Since these rules are supposed to
3805 * be processed before all http-request rules, we put them into their own list
3806 * and will insert them at the end.
3807 */
3808 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3809 if (!rule) {
3810 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003811 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003812 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003813 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3814 err_code |= warnif_cond_conflicts(rule->cond,
3815 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3816 file, linenum);
3817 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003818
3819 if (!already_warned(WARN_BLOCK_DEPRECATED))
3820 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]);
3821
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003822 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003823 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003824 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003825
Cyril Bonté99ed3272010-01-24 23:29:44 +01003826 if (curproxy == &defproxy) {
3827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831
Willy Tarreaube4653b2015-05-28 15:26:58 +02003832 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003833 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3834 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003837 }
3838
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003839 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003840 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003841 err_code |= warnif_cond_conflicts(rule->cond,
3842 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3843 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003844 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003845 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003846 struct switching_rule *rule;
3847
Willy Tarreaub099aca2008-10-12 17:26:37 +02003848 if (curproxy == &defproxy) {
3849 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003852 }
3853
Willy Tarreau55ea7572007-06-17 19:56:27 +02003854 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003856
3857 if (*(args[1]) == 0) {
3858 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003861 }
3862
Willy Tarreauf51658d2014-04-23 01:21:56 +02003863 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3864 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3865 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3866 file, linenum, errmsg);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003870
Willy Tarreauf51658d2014-04-23 01:21:56 +02003871 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003872 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003873 else if (*args[2]) {
3874 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3875 file, linenum, args[2]);
3876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003879
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003880 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003881 if (!rule) {
3882 Alert("Out of memory error.\n");
3883 goto out;
3884 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003885 rule->cond = cond;
3886 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003887 rule->line = linenum;
3888 rule->file = strdup(file);
3889 if (!rule->file) {
3890 Alert("Out of memory error.\n");
3891 goto out;
3892 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003893 LIST_INIT(&rule->list);
3894 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3895 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003896 else if (strcmp(args[0], "use-server") == 0) {
3897 struct server_rule *rule;
3898
3899 if (curproxy == &defproxy) {
3900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
3904
3905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3906 err_code |= ERR_WARN;
3907
3908 if (*(args[1]) == 0) {
3909 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
3912 }
3913
3914 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3915 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3916 file, linenum, args[0]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
3920
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003921 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3922 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3923 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003928 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003929
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003930 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003931 rule->cond = cond;
3932 rule->srv.name = strdup(args[1]);
3933 LIST_INIT(&rule->list);
3934 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3935 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3936 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003937 else if ((!strcmp(args[0], "force-persist")) ||
3938 (!strcmp(args[0], "ignore-persist"))) {
3939 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003940
3941 if (curproxy == &defproxy) {
3942 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
3945 }
3946
3947 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3948 err_code |= ERR_WARN;
3949
Willy Tarreauef6494c2010-01-28 17:12:36 +01003950 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003951 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3952 file, linenum, args[0]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003957 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3958 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3959 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
3962 }
3963
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003964 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3965 * where force-persist is applied.
3966 */
3967 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003968
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003969 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003970 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003971 if (!strcmp(args[0], "force-persist")) {
3972 rule->type = PERSIST_TYPE_FORCE;
3973 } else {
3974 rule->type = PERSIST_TYPE_IGNORE;
3975 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003976 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003977 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003978 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003979 else if (!strcmp(args[0], "stick-table")) {
3980 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003981 struct proxy *other;
3982
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003983 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003984 if (other) {
3985 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3986 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003990
Emeric Brun32da3c42010-09-23 18:39:19 +02003991 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003992 curproxy->table.type = (unsigned int)-1;
3993 while (*args[myidx]) {
3994 const char *err;
3995
3996 if (strcmp(args[myidx], "size") == 0) {
3997 myidx++;
3998 if (!*(args[myidx])) {
3999 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4000 file, linenum, args[myidx-1]);
4001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
4003 }
4004 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4005 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4006 file, linenum, *err, args[myidx-1]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004010 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004011 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004012 else if (strcmp(args[myidx], "peers") == 0) {
4013 myidx++;
Godbach50523162013-12-11 19:48:57 +08004014 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004015 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4016 file, linenum, args[myidx-1]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Godbach50523162013-12-11 19:48:57 +08004019 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004020 curproxy->table.peers.name = strdup(args[myidx++]);
4021 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004022 else if (strcmp(args[myidx], "expire") == 0) {
4023 myidx++;
4024 if (!*(args[myidx])) {
4025 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4026 file, linenum, args[myidx-1]);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
4030 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4031 if (err) {
4032 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4033 file, linenum, *err, args[myidx-1]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004037 if (val > INT_MAX) {
4038 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4039 file, linenum, val);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004043 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004044 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004045 }
4046 else if (strcmp(args[myidx], "nopurge") == 0) {
4047 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004048 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004049 }
4050 else if (strcmp(args[myidx], "type") == 0) {
4051 myidx++;
4052 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4053 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4054 file, linenum, args[myidx]);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004058 /* myidx already points to next arg */
4059 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004060 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004061 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004062 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004063
4064 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004065 nw = args[myidx];
4066 while (*nw) {
4067 /* the "store" keyword supports a comma-separated list */
4068 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004069 sa = NULL; /* store arg */
4070 while (*nw && *nw != ',') {
4071 if (*nw == '(') {
4072 *nw = 0;
4073 sa = ++nw;
4074 while (*nw != ')') {
4075 if (!*nw) {
4076 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4077 file, linenum, args[0], cw);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
4081 nw++;
4082 }
4083 *nw = '\0';
4084 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004085 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004086 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004087 if (*nw)
4088 *nw++ = '\0';
4089 type = stktable_get_data_type(cw);
4090 if (type < 0) {
4091 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4092 file, linenum, args[0], cw);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
Willy Tarreauac782882010-06-20 10:41:54 +02004096
4097 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4098 switch (err) {
4099 case PE_NONE: break;
4100 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004101 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4102 file, linenum, args[0], cw);
4103 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004104 break;
4105
4106 case PE_ARG_MISSING:
4107 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4108 file, linenum, args[0], cw);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111
4112 case PE_ARG_NOT_USED:
4113 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4114 file, linenum, args[0], cw);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117
4118 default:
4119 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4120 file, linenum, args[0], cw);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004123 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004124 }
4125 myidx++;
4126 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004127 else {
4128 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4129 file, linenum, args[myidx]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 }
4134
4135 if (!curproxy->table.size) {
4136 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4137 file, linenum);
4138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141
4142 if (curproxy->table.type == (unsigned int)-1) {
4143 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4144 file, linenum);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148 }
4149 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004151 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 int myidx = 0;
4153 const char *name = NULL;
4154 int flags;
4155
4156 if (curproxy == &defproxy) {
4157 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
4161
4162 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4163 err_code |= ERR_WARN;
4164 goto out;
4165 }
4166
4167 myidx++;
4168 if ((strcmp(args[myidx], "store") == 0) ||
4169 (strcmp(args[myidx], "store-request") == 0)) {
4170 myidx++;
4171 flags = STK_IS_STORE;
4172 }
4173 else if (strcmp(args[myidx], "store-response") == 0) {
4174 myidx++;
4175 flags = STK_IS_STORE | STK_ON_RSP;
4176 }
4177 else if (strcmp(args[myidx], "match") == 0) {
4178 myidx++;
4179 flags = STK_IS_MATCH;
4180 }
4181 else if (strcmp(args[myidx], "on") == 0) {
4182 myidx++;
4183 flags = STK_IS_MATCH | STK_IS_STORE;
4184 }
4185 else {
4186 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190
4191 if (*(args[myidx]) == 0) {
4192 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004197 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004198 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004199 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004200 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
4204
4205 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004206 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4207 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\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 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004214 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4215 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4216 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004217 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004218 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004219 goto out;
4220 }
4221 }
4222
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004223 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004224 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004225
Emeric Brunb982a3d2010-01-04 15:45:53 +01004226 if (strcmp(args[myidx], "table") == 0) {
4227 myidx++;
4228 name = args[myidx++];
4229 }
4230
Willy Tarreauef6494c2010-01-28 17:12:36 +01004231 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004232 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4233 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4234 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004235 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004236 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004237 goto out;
4238 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004240 else if (*(args[myidx])) {
4241 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4242 file, linenum, args[0], args[myidx]);
4243 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004244 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004245 goto out;
4246 }
Emeric Brun97679e72010-09-23 17:56:44 +02004247 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004248 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004249 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004250 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004251
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004252 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004253 rule->cond = cond;
4254 rule->expr = expr;
4255 rule->flags = flags;
4256 rule->table.name = name ? strdup(name) : NULL;
4257 LIST_INIT(&rule->list);
4258 if (flags & STK_ON_RSP)
4259 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4260 else
4261 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 else if (!strcmp(args[0], "stats")) {
4264 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4265 curproxy->uri_auth = NULL; /* we must detach from the default config */
4266
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004267 if (!*args[1]) {
4268 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004269 } else if (!strcmp(args[1], "admin")) {
4270 struct stats_admin_rule *rule;
4271
4272 if (curproxy == &defproxy) {
4273 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
4277
4278 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4279 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4280 err_code |= ERR_ALERT | ERR_ABORT;
4281 goto out;
4282 }
4283
4284 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4285 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4286 file, linenum, args[0], args[1]);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004290 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4291 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4292 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004297 err_code |= warnif_cond_conflicts(cond,
4298 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4299 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004300
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004301 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004302 rule->cond = cond;
4303 LIST_INIT(&rule->list);
4304 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 } else if (!strcmp(args[1], "uri")) {
4306 if (*(args[2]) == 0) {
4307 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_ABORT;
4313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 }
4315 } else if (!strcmp(args[1], "realm")) {
4316 if (*(args[2]) == 0) {
4317 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004322 err_code |= ERR_ALERT | ERR_ABORT;
4323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004325 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004326 unsigned interval;
4327
4328 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4329 if (err) {
4330 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4331 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004334 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4335 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_ABORT;
4337 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004338 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004339 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004340 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004341
4342 if (curproxy == &defproxy) {
4343 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347
4348 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4349 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4350 err_code |= ERR_ALERT | ERR_ABORT;
4351 goto out;
4352 }
4353
Willy Tarreauff011f22011-01-06 17:51:27 +01004354 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004355 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004356 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4357 file, linenum, args[0]);
4358 err_code |= ERR_WARN;
4359 }
4360
Willy Tarreauff011f22011-01-06 17:51:27 +01004361 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004362
Willy Tarreauff011f22011-01-06 17:51:27 +01004363 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004364 err_code |= ERR_ALERT | ERR_ABORT;
4365 goto out;
4366 }
4367
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004368 err_code |= warnif_cond_conflicts(rule->cond,
4369 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4370 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004371 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004372
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 } else if (!strcmp(args[1], "auth")) {
4374 if (*(args[2]) == 0) {
4375 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_ALERT | ERR_ABORT;
4381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 }
4383 } else if (!strcmp(args[1], "scope")) {
4384 if (*(args[2]) == 0) {
4385 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_ABORT;
4391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 }
4393 } else if (!strcmp(args[1], "enable")) {
4394 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_ABORT;
4397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004399 } else if (!strcmp(args[1], "hide-version")) {
4400 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_ABORT;
4403 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004404 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004405 } else if (!strcmp(args[1], "show-legends")) {
4406 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4407 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4408 err_code |= ERR_ALERT | ERR_ABORT;
4409 goto out;
4410 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004411 } else if (!strcmp(args[1], "show-node")) {
4412
4413 if (*args[2]) {
4414 int i;
4415 char c;
4416
4417 for (i=0; args[2][i]; i++) {
4418 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004419 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4420 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004421 break;
4422 }
4423
4424 if (!i || args[2][i]) {
4425 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4426 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4427 file, linenum, args[0], args[1]);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 }
4431 }
4432
4433 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4434 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4435 err_code |= ERR_ALERT | ERR_ABORT;
4436 goto out;
4437 }
4438 } else if (!strcmp(args[1], "show-desc")) {
4439 char *desc = NULL;
4440
4441 if (*args[2]) {
4442 int i, len=0;
4443 char *d;
4444
Willy Tarreau348acfe2014-04-14 15:00:39 +02004445 for (i = 2; *args[i]; i++)
4446 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004447
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004448 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004449
Willy Tarreau348acfe2014-04-14 15:00:39 +02004450 d += snprintf(d, desc + len - d, "%s", args[2]);
4451 for (i = 3; *args[i]; i++)
4452 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004453 }
4454
4455 if (!*args[2] && !global.desc)
4456 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4457 file, linenum, args[1]);
4458 else {
4459 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4460 free(desc);
4461 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4462 err_code |= ERR_ALERT | ERR_ABORT;
4463 goto out;
4464 }
4465 free(desc);
4466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004468stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004469 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 +01004470 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
4474 }
4475 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004476 int optnum;
4477
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004478 if (*(args[1]) == '\0') {
4479 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004484
4485 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4486 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004487 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4488 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4489 file, linenum, cfg_opts[optnum].name);
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
4492 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004493 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4494 goto out;
4495
Willy Tarreau93893792009-07-23 13:19:11 +02004496 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4497 err_code |= ERR_WARN;
4498 goto out;
4499 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004500
Willy Tarreau3842f002009-06-14 11:39:52 +02004501 curproxy->no_options &= ~cfg_opts[optnum].val;
4502 curproxy->options &= ~cfg_opts[optnum].val;
4503
4504 switch (kwm) {
4505 case KWM_STD:
4506 curproxy->options |= cfg_opts[optnum].val;
4507 break;
4508 case KWM_NO:
4509 curproxy->no_options |= cfg_opts[optnum].val;
4510 break;
4511 case KWM_DEF: /* already cleared */
4512 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004513 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004514
Willy Tarreau93893792009-07-23 13:19:11 +02004515 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004516 }
4517 }
4518
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004519 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4520 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004521 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4522 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4523 file, linenum, cfg_opts2[optnum].name);
4524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
4526 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004527 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4528 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004529 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4530 err_code |= ERR_WARN;
4531 goto out;
4532 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004533
Willy Tarreau3842f002009-06-14 11:39:52 +02004534 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4535 curproxy->options2 &= ~cfg_opts2[optnum].val;
4536
4537 switch (kwm) {
4538 case KWM_STD:
4539 curproxy->options2 |= cfg_opts2[optnum].val;
4540 break;
4541 case KWM_NO:
4542 curproxy->no_options2 |= cfg_opts2[optnum].val;
4543 break;
4544 case KWM_DEF: /* already cleared */
4545 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004546 }
Willy Tarreau93893792009-07-23 13:19:11 +02004547 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004548 }
4549 }
4550
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004551 /* HTTP options override each other. They can be cancelled using
4552 * "no option xxx" which only switches to default mode if the mode
4553 * was this one (useful for cancelling options set in defaults
4554 * sections).
4555 */
4556 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004557 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4558 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004559 if (kwm == KWM_STD) {
4560 curproxy->options &= ~PR_O_HTTP_MODE;
4561 curproxy->options |= PR_O_HTTP_PCL;
4562 goto out;
4563 }
4564 else if (kwm == KWM_NO) {
4565 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 goto out;
4568 }
4569 }
4570 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004571 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4572 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004573 if (kwm == KWM_STD) {
4574 curproxy->options &= ~PR_O_HTTP_MODE;
4575 curproxy->options |= PR_O_HTTP_FCL;
4576 goto out;
4577 }
4578 else if (kwm == KWM_NO) {
4579 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 goto out;
4582 }
4583 }
4584 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004585 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4586 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004587 if (kwm == KWM_STD) {
4588 curproxy->options &= ~PR_O_HTTP_MODE;
4589 curproxy->options |= PR_O_HTTP_SCL;
4590 goto out;
4591 }
4592 else if (kwm == KWM_NO) {
4593 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4594 curproxy->options &= ~PR_O_HTTP_MODE;
4595 goto out;
4596 }
4597 }
4598 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004599 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4600 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004601 if (kwm == KWM_STD) {
4602 curproxy->options &= ~PR_O_HTTP_MODE;
4603 curproxy->options |= PR_O_HTTP_KAL;
4604 goto out;
4605 }
4606 else if (kwm == KWM_NO) {
4607 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4608 curproxy->options &= ~PR_O_HTTP_MODE;
4609 goto out;
4610 }
4611 }
4612 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004613 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4614 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004615 if (kwm == KWM_STD) {
4616 curproxy->options &= ~PR_O_HTTP_MODE;
4617 curproxy->options |= PR_O_HTTP_TUN;
4618 goto out;
4619 }
4620 else if (kwm == KWM_NO) {
4621 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4622 curproxy->options &= ~PR_O_HTTP_MODE;
4623 goto out;
4624 }
4625 }
4626
Joseph Lynch726ab712015-05-11 23:25:34 -07004627 /* Redispatch can take an integer argument that control when the
4628 * resispatch occurs. All values are relative to the retries option.
4629 * This can be cancelled using "no option xxx".
4630 */
4631 if (strcmp(args[1], "redispatch") == 0) {
4632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4633 err_code |= ERR_WARN;
4634 goto out;
4635 }
4636
4637 curproxy->no_options &= ~PR_O_REDISP;
4638 curproxy->options &= ~PR_O_REDISP;
4639
4640 switch (kwm) {
4641 case KWM_STD:
4642 curproxy->options |= PR_O_REDISP;
4643 curproxy->redispatch_after = -1;
4644 if(*args[2]) {
4645 curproxy->redispatch_after = atol(args[2]);
4646 }
4647 break;
4648 case KWM_NO:
4649 curproxy->no_options |= PR_O_REDISP;
4650 curproxy->redispatch_after = 0;
4651 break;
4652 case KWM_DEF: /* already cleared */
4653 break;
4654 }
4655 goto out;
4656 }
4657
Willy Tarreau3842f002009-06-14 11:39:52 +02004658 if (kwm != KWM_STD) {
4659 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004660 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004661 err_code |= ERR_ALERT | ERR_FATAL;
4662 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004663 }
4664
Emeric Brun3a058f32009-06-30 18:26:00 +02004665 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004666 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004668 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004669 if (*(args[2]) != '\0') {
4670 if (!strcmp(args[2], "clf")) {
4671 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004672 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004673 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004674 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004677 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004678 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4679 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004680 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004681 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4682 char *oldlogformat = "log-format";
4683 char *clflogformat = "";
4684
4685 if (curproxy->conf.logformat_string == default_http_log_format)
4686 oldlogformat = "option httplog";
4687 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4688 oldlogformat = "option tcplog";
4689 else if (curproxy->conf.logformat_string == clf_http_log_format)
4690 oldlogformat = "option httplog clf";
4691 if (logformat == clf_http_log_format)
4692 clflogformat = " clf";
4693 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4694 file, linenum, clflogformat, oldlogformat);
4695 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004696 if (curproxy->conf.logformat_string != default_http_log_format &&
4697 curproxy->conf.logformat_string != default_tcp_log_format &&
4698 curproxy->conf.logformat_string != clf_http_log_format)
4699 free(curproxy->conf.logformat_string);
4700 curproxy->conf.logformat_string = logformat;
4701
4702 free(curproxy->conf.lfs_file);
4703 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4704 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004705 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004706 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004707 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4708 char *oldlogformat = "log-format";
4709
4710 if (curproxy->conf.logformat_string == default_http_log_format)
4711 oldlogformat = "option httplog";
4712 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4713 oldlogformat = "option tcplog";
4714 else if (curproxy->conf.logformat_string == clf_http_log_format)
4715 oldlogformat = "option httplog clf";
4716 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4717 file, linenum, oldlogformat);
4718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004720 if (curproxy->conf.logformat_string != default_http_log_format &&
4721 curproxy->conf.logformat_string != default_tcp_log_format &&
4722 curproxy->conf.logformat_string != clf_http_log_format)
4723 free(curproxy->conf.logformat_string);
4724 curproxy->conf.logformat_string = default_tcp_log_format;
4725
4726 free(curproxy->conf.lfs_file);
4727 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4728 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004729
4730 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4731 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004734 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004735 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004736 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004737
William Lallemanddf1425a2015-04-28 20:17:49 +02004738 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4739 goto out;
4740
Willy Tarreau13943ab2006-12-31 00:24:10 +01004741 if (curproxy->cap & PR_CAP_FE)
4742 curproxy->options |= PR_O_TCP_CLI_KA;
4743 if (curproxy->cap & PR_CAP_BE)
4744 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 }
4746 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_WARN;
4749
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004751 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004752 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004753 curproxy->options2 &= ~PR_O2_CHK_ANY;
4754 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 if (!*args[2]) { /* no argument */
4756 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4757 curproxy->check_len = strlen(DEF_CHECK_REQ);
4758 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004759 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004760 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004762 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004764 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 if (*args[4])
4766 reqlen += strlen(args[4]);
4767 else
4768 reqlen += strlen("HTTP/1.0");
4769
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004770 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004772 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004774 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4775 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004776 }
4777 else if (!strcmp(args[1], "ssl-hello-chk")) {
4778 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004779 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004780 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004781
Willy Tarreaua534fea2008-08-03 12:19:50 +02004782 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004783 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004784 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004785 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004786
4787 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 }
Willy Tarreau23677902007-05-08 23:50:35 +02004790 else if (!strcmp(args[1], "smtpchk")) {
4791 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004792 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004793 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004794 curproxy->options2 &= ~PR_O2_CHK_ANY;
4795 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004796
4797 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4798 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4799 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4800 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4801 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4802 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004803 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004804 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4805 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4806 } else {
4807 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4808 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4809 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4810 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4811 }
4812 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004813 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4814 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004815 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004816 else if (!strcmp(args[1], "pgsql-check")) {
4817 /* use PostgreSQL request to check servers' health */
4818 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4819 err_code |= ERR_WARN;
4820
4821 free(curproxy->check_req);
4822 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004823 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004824 curproxy->options2 |= PR_O2_PGSQL_CHK;
4825
4826 if (*(args[2])) {
4827 int cur_arg = 2;
4828
4829 while (*(args[cur_arg])) {
4830 if (strcmp(args[cur_arg], "user") == 0) {
4831 char * packet;
4832 uint32_t packet_len;
4833 uint32_t pv;
4834
4835 /* suboption header - needs additional argument for it */
4836 if (*(args[cur_arg+1]) == 0) {
4837 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4838 file, linenum, args[0], args[1], args[cur_arg]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
4842
4843 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4844 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4845 pv = htonl(0x30000); /* protocol version 3.0 */
4846
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004847 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004848
4849 memcpy(packet + 4, &pv, 4);
4850
4851 /* copy "user" */
4852 memcpy(packet + 8, "user", 4);
4853
4854 /* copy username */
4855 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4856
4857 free(curproxy->check_req);
4858 curproxy->check_req = packet;
4859 curproxy->check_len = packet_len;
4860
4861 packet_len = htonl(packet_len);
4862 memcpy(packet, &packet_len, 4);
4863 cur_arg += 2;
4864 } else {
4865 /* unknown suboption - catchall */
4866 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4867 file, linenum, args[0], args[1]);
4868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
4871 } /* end while loop */
4872 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004873 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4874 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004875 }
4876
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004877 else if (!strcmp(args[1], "redis-check")) {
4878 /* use REDIS PING request to check servers' health */
4879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4880 err_code |= ERR_WARN;
4881
4882 free(curproxy->check_req);
4883 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004884 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004885 curproxy->options2 |= PR_O2_REDIS_CHK;
4886
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004887 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004888 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4889 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004890
4891 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4892 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004893 }
4894
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004895 else if (!strcmp(args[1], "mysql-check")) {
4896 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4898 err_code |= ERR_WARN;
4899
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004900 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004901 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004902 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004903 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004904
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004905 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004906 * const char mysql40_client_auth_pkt[] = {
4907 * "\x0e\x00\x00" // packet length
4908 * "\x01" // packet number
4909 * "\x00\x00" // client capabilities
4910 * "\x00\x00\x01" // max packet
4911 * "haproxy\x00" // username (null terminated string)
4912 * "\x00" // filler (always 0x00)
4913 * "\x01\x00\x00" // packet length
4914 * "\x00" // packet number
4915 * "\x01" // COM_QUIT command
4916 * };
4917 */
4918
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004919 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4920 * const char mysql41_client_auth_pkt[] = {
4921 * "\x0e\x00\x00\" // packet length
4922 * "\x01" // packet number
4923 * "\x00\x00\x00\x00" // client capabilities
4924 * "\x00\x00\x00\x01" // max packet
4925 * "\x21" // character set (UTF-8)
4926 * char[23] // All zeroes
4927 * "haproxy\x00" // username (null terminated string)
4928 * "\x00" // filler (always 0x00)
4929 * "\x01\x00\x00" // packet length
4930 * "\x00" // packet number
4931 * "\x01" // COM_QUIT command
4932 * };
4933 */
4934
4935
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004936 if (*(args[2])) {
4937 int cur_arg = 2;
4938
4939 while (*(args[cur_arg])) {
4940 if (strcmp(args[cur_arg], "user") == 0) {
4941 char *mysqluser;
4942 int packetlen, reqlen, userlen;
4943
4944 /* suboption header - needs additional argument for it */
4945 if (*(args[cur_arg+1]) == 0) {
4946 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4947 file, linenum, args[0], args[1], args[cur_arg]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951 mysqluser = args[cur_arg + 1];
4952 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004953
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004954 if (*(args[cur_arg+2])) {
4955 if (!strcmp(args[cur_arg+2], "post-41")) {
4956 packetlen = userlen + 7 + 27;
4957 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004958
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004959 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004960 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004961 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004962
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004963 snprintf(curproxy->check_req, 4, "%c%c%c",
4964 ((unsigned char) packetlen & 0xff),
4965 ((unsigned char) (packetlen >> 8) & 0xff),
4966 ((unsigned char) (packetlen >> 16) & 0xff));
4967
4968 curproxy->check_req[3] = 1;
4969 curproxy->check_req[5] = 130;
4970 curproxy->check_req[11] = 1;
4971 curproxy->check_req[12] = 33;
4972 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4973 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4974 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4975 cur_arg += 3;
4976 } else {
4977 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981 } else {
4982 packetlen = userlen + 7;
4983 reqlen = packetlen + 9;
4984
4985 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004986 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004987 curproxy->check_len = reqlen;
4988
4989 snprintf(curproxy->check_req, 4, "%c%c%c",
4990 ((unsigned char) packetlen & 0xff),
4991 ((unsigned char) (packetlen >> 8) & 0xff),
4992 ((unsigned char) (packetlen >> 16) & 0xff));
4993
4994 curproxy->check_req[3] = 1;
4995 curproxy->check_req[5] = 128;
4996 curproxy->check_req[8] = 1;
4997 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4998 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4999 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5000 cur_arg += 2;
5001 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005002 } else {
5003 /* unknown suboption - catchall */
5004 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5005 file, linenum, args[0], args[1]);
5006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
5009 } /* end while loop */
5010 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005011 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005012 else if (!strcmp(args[1], "ldap-check")) {
5013 /* use LDAP request to check servers' health */
5014 free(curproxy->check_req);
5015 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005016 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005017 curproxy->options2 |= PR_O2_LDAP_CHK;
5018
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005019 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005020 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5021 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005022 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5023 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005024 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005025 else if (!strcmp(args[1], "spop-check")) {
5026 if (curproxy == &defproxy) {
5027 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5028 file, linenum, args[0], args[1]);
5029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
5031 }
5032 if (curproxy->cap & PR_CAP_FE) {
5033 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5034 file, linenum, args[0], args[1]);
5035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
5037 }
5038
5039 /* use SPOE request to check servers' health */
5040 free(curproxy->check_req);
5041 curproxy->check_req = NULL;
5042 curproxy->options2 &= ~PR_O2_CHK_ANY;
5043 curproxy->options2 |= PR_O2_SPOP_CHK;
5044
Christopher Faulet8ef75252017-02-20 22:56:03 +01005045 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005046 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
5050 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5051 goto out;
5052 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005053 else if (!strcmp(args[1], "tcp-check")) {
5054 /* use raw TCPCHK send/expect to check servers' health */
5055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5056 err_code |= ERR_WARN;
5057
5058 free(curproxy->check_req);
5059 curproxy->check_req = NULL;
5060 curproxy->options2 &= ~PR_O2_CHK_ANY;
5061 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005062 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5063 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005064 }
Simon Horman98637e52014-06-20 12:30:16 +09005065 else if (!strcmp(args[1], "external-check")) {
5066 /* excute an external command to check servers' health */
5067 free(curproxy->check_req);
5068 curproxy->check_req = NULL;
5069 curproxy->options2 &= ~PR_O2_CHK_ANY;
5070 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005071 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5072 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005073 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005074 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005075 int cur_arg;
5076
5077 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5078 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005079 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005080
Willy Tarreau87cf5142011-08-19 22:57:24 +02005081 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005082
5083 free(curproxy->fwdfor_hdr_name);
5084 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5085 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5086
5087 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5088 cur_arg = 2;
5089 while (*(args[cur_arg])) {
5090 if (!strcmp(args[cur_arg], "except")) {
5091 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005092 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005093 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5094 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005097 }
5098 /* flush useless bits */
5099 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005100 cur_arg += 2;
5101 } else if (!strcmp(args[cur_arg], "header")) {
5102 /* suboption header - needs additional argument for it */
5103 if (*(args[cur_arg+1]) == 0) {
5104 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5105 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005108 }
5109 free(curproxy->fwdfor_hdr_name);
5110 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5111 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5112 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005113 } else if (!strcmp(args[cur_arg], "if-none")) {
5114 curproxy->options &= ~PR_O_FF_ALWAYS;
5115 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005116 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005117 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005118 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005119 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005122 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005123 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005124 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005125 else if (!strcmp(args[1], "originalto")) {
5126 int cur_arg;
5127
5128 /* insert x-original-to field, but not for the IP address listed as an except.
5129 * set default options (ie: bitfield, header name, etc)
5130 */
5131
5132 curproxy->options |= PR_O_ORGTO;
5133
5134 free(curproxy->orgto_hdr_name);
5135 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5136 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5137
Willy Tarreau87cf5142011-08-19 22:57:24 +02005138 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005139 cur_arg = 2;
5140 while (*(args[cur_arg])) {
5141 if (!strcmp(args[cur_arg], "except")) {
5142 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005143 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 +02005144 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5145 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005148 }
5149 /* flush useless bits */
5150 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5151 cur_arg += 2;
5152 } else if (!strcmp(args[cur_arg], "header")) {
5153 /* suboption header - needs additional argument for it */
5154 if (*(args[cur_arg+1]) == 0) {
5155 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5156 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005159 }
5160 free(curproxy->orgto_hdr_name);
5161 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5162 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5163 cur_arg += 2;
5164 } else {
5165 /* unknown suboption - catchall */
5166 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5167 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005170 }
5171 } /* end while loop */
5172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 else {
5174 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreau93893792009-07-23 13:19:11 +02005178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005180 else if (!strcmp(args[0], "default_backend")) {
5181 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005183
5184 if (*(args[1]) == 0) {
5185 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005188 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005189 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005190 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005191
5192 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5193 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005196 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005198
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005199 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5200 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 +01005201 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 /* enable reconnections to dispatch */
5204 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005205
5206 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005209 else if (!strcmp(args[0], "http-reuse")) {
5210 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5211 err_code |= ERR_WARN;
5212
5213 if (strcmp(args[1], "never") == 0) {
5214 /* enable a graceful server shutdown on an HTTP 404 response */
5215 curproxy->options &= ~PR_O_REUSE_MASK;
5216 curproxy->options |= PR_O_REUSE_NEVR;
5217 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5218 goto out;
5219 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005220 else if (strcmp(args[1], "safe") == 0) {
5221 /* enable a graceful server shutdown on an HTTP 404 response */
5222 curproxy->options &= ~PR_O_REUSE_MASK;
5223 curproxy->options |= PR_O_REUSE_SAFE;
5224 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5225 goto out;
5226 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005227 else if (strcmp(args[1], "aggressive") == 0) {
5228 curproxy->options &= ~PR_O_REUSE_MASK;
5229 curproxy->options |= PR_O_REUSE_AGGR;
5230 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5231 goto out;
5232 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005233 else if (strcmp(args[1], "always") == 0) {
5234 /* enable a graceful server shutdown on an HTTP 404 response */
5235 curproxy->options &= ~PR_O_REUSE_MASK;
5236 curproxy->options |= PR_O_REUSE_ALWS;
5237 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5238 goto out;
5239 }
5240 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005241 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
5244 }
5245 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005246 else if (!strcmp(args[0], "http-check")) {
5247 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005248 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005249
5250 if (strcmp(args[1], "disable-on-404") == 0) {
5251 /* enable a graceful server shutdown on an HTTP 404 response */
5252 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005253 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5254 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005255 }
Willy Tarreauef781042010-01-27 11:53:01 +01005256 else if (strcmp(args[1], "send-state") == 0) {
5257 /* enable emission of the apparent state of a server in HTTP checks */
5258 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005259 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5260 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005261 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005262 else if (strcmp(args[1], "expect") == 0) {
5263 const char *ptr_arg;
5264 int cur_arg;
5265
5266 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5267 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271
5272 cur_arg = 2;
5273 /* consider exclamation marks, sole or at the beginning of a word */
5274 while (*(ptr_arg = args[cur_arg])) {
5275 while (*ptr_arg == '!') {
5276 curproxy->options2 ^= PR_O2_EXP_INV;
5277 ptr_arg++;
5278 }
5279 if (*ptr_arg)
5280 break;
5281 cur_arg++;
5282 }
5283 /* now ptr_arg points to the beginning of a word past any possible
5284 * exclamation mark, and cur_arg is the argument which holds this word.
5285 */
5286 if (strcmp(ptr_arg, "status") == 0) {
5287 if (!*(args[cur_arg + 1])) {
5288 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5289 file, linenum, args[0], args[1], ptr_arg);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005294 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005295 curproxy->expect_str = strdup(args[cur_arg + 1]);
5296 }
5297 else if (strcmp(ptr_arg, "string") == 0) {
5298 if (!*(args[cur_arg + 1])) {
5299 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5300 file, linenum, args[0], args[1], ptr_arg);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005305 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005306 curproxy->expect_str = strdup(args[cur_arg + 1]);
5307 }
5308 else if (strcmp(ptr_arg, "rstatus") == 0) {
5309 if (!*(args[cur_arg + 1])) {
5310 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5311 file, linenum, args[0], args[1], ptr_arg);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005316 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005317 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005318 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005319 free(curproxy->expect_regex);
5320 curproxy->expect_regex = NULL;
5321 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005322 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005323 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5324 error = NULL;
5325 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5326 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5327 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5328 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332 }
5333 else if (strcmp(ptr_arg, "rstring") == 0) {
5334 if (!*(args[cur_arg + 1])) {
5335 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5336 file, linenum, args[0], args[1], ptr_arg);
5337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
5339 }
5340 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005341 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005342 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005343 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005344 free(curproxy->expect_regex);
5345 curproxy->expect_regex = NULL;
5346 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005347 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005348 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5349 error = NULL;
5350 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5351 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5352 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5353 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357 }
5358 else {
5359 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5360 file, linenum, args[0], args[1], ptr_arg);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005365 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005366 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 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005369 }
5370 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005371 else if (!strcmp(args[0], "tcp-check")) {
5372 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5373 err_code |= ERR_WARN;
5374
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005375 if (strcmp(args[1], "comment") == 0) {
5376 int cur_arg;
5377 struct tcpcheck_rule *tcpcheck;
5378
5379 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005380 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005381 tcpcheck->action = TCPCHK_ACT_COMMENT;
5382
5383 if (!*args[cur_arg + 1]) {
5384 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5385 file, linenum, args[cur_arg]);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389
5390 tcpcheck->comment = strdup(args[cur_arg + 1]);
5391
5392 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005393 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5394 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005395 }
5396 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005397 const char *ptr_arg;
5398 int cur_arg;
5399 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005400
5401 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005402 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5403 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5404 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5405 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5406 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005407
Willy Tarreau5581c272015-05-13 12:24:53 +02005408 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5409 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5410 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5411 file, linenum);
5412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005414 }
5415
5416 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005417 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005418 tcpcheck->action = TCPCHK_ACT_CONNECT;
5419
5420 /* parsing each parameters to fill up the rule */
5421 while (*(ptr_arg = args[cur_arg])) {
5422 /* tcp port */
5423 if (strcmp(args[cur_arg], "port") == 0) {
5424 if ( (atol(args[cur_arg + 1]) > 65535) ||
5425 (atol(args[cur_arg + 1]) < 1) ){
5426 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5427 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431 tcpcheck->port = atol(args[cur_arg + 1]);
5432 cur_arg += 2;
5433 }
5434 /* send proxy protocol */
5435 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5436 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5437 cur_arg++;
5438 }
5439#ifdef USE_OPENSSL
5440 else if (strcmp(args[cur_arg], "ssl") == 0) {
5441 curproxy->options |= PR_O_TCPCHK_SSL;
5442 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5443 cur_arg++;
5444 }
5445#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005446 /* comment for this tcpcheck line */
5447 else if (strcmp(args[cur_arg], "comment") == 0) {
5448 if (!*args[cur_arg + 1]) {
5449 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5450 file, linenum, args[cur_arg]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 tcpcheck->comment = strdup(args[cur_arg + 1]);
5455 cur_arg += 2;
5456 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005457 else {
5458#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005459 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 +01005460#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005461 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 +01005462#endif /* USE_OPENSSL */
5463 file, linenum, args[0], args[1], args[cur_arg]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467
5468 }
5469
5470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5471 }
5472 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005473 if (! *(args[2]) ) {
5474 /* SEND string expected */
5475 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5476 file, linenum, args[0], args[1], args[2]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 } else {
5480 struct tcpcheck_rule *tcpcheck;
5481
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005482 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005483
5484 tcpcheck->action = TCPCHK_ACT_SEND;
5485 tcpcheck->string_len = strlen(args[2]);
5486 tcpcheck->string = strdup(args[2]);
5487 tcpcheck->expect_regex = NULL;
5488
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005489 /* comment for this tcpcheck line */
5490 if (strcmp(args[3], "comment") == 0) {
5491 if (!*args[4]) {
5492 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5493 file, linenum, args[3]);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 tcpcheck->comment = strdup(args[4]);
5498 }
5499
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5501 }
5502 }
5503 else if (strcmp(args[1], "send-binary") == 0) {
5504 if (! *(args[2]) ) {
5505 /* SEND binary string expected */
5506 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5507 file, linenum, args[0], args[1], args[2]);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 } else {
5511 struct tcpcheck_rule *tcpcheck;
5512 char *err = NULL;
5513
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005514 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515
5516 tcpcheck->action = TCPCHK_ACT_SEND;
5517 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5518 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5519 file, linenum, args[0], args[1], args[2], err);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
5523 tcpcheck->expect_regex = NULL;
5524
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005525 /* comment for this tcpcheck line */
5526 if (strcmp(args[3], "comment") == 0) {
5527 if (!*args[4]) {
5528 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5529 file, linenum, args[3]);
5530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532 }
5533 tcpcheck->comment = strdup(args[4]);
5534 }
5535
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5537 }
5538 }
5539 else if (strcmp(args[1], "expect") == 0) {
5540 const char *ptr_arg;
5541 int cur_arg;
5542 int inverse = 0;
5543
5544 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5545 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
5549
5550 cur_arg = 2;
5551 /* consider exclamation marks, sole or at the beginning of a word */
5552 while (*(ptr_arg = args[cur_arg])) {
5553 while (*ptr_arg == '!') {
5554 inverse = !inverse;
5555 ptr_arg++;
5556 }
5557 if (*ptr_arg)
5558 break;
5559 cur_arg++;
5560 }
5561 /* now ptr_arg points to the beginning of a word past any possible
5562 * exclamation mark, and cur_arg is the argument which holds this word.
5563 */
5564 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005565 struct tcpcheck_rule *tcpcheck;
5566 char *err = NULL;
5567
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568 if (!*(args[cur_arg + 1])) {
5569 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5570 file, linenum, args[0], args[1], ptr_arg);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005574
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005575 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005576
5577 tcpcheck->action = TCPCHK_ACT_EXPECT;
5578 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5579 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5580 file, linenum, args[0], args[1], args[2], err);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
5584 tcpcheck->expect_regex = NULL;
5585 tcpcheck->inverse = inverse;
5586
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005587 /* tcpcheck comment */
5588 cur_arg += 2;
5589 if (strcmp(args[cur_arg], "comment") == 0) {
5590 if (!*args[cur_arg + 1]) {
5591 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5592 file, linenum, args[cur_arg + 1]);
5593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 tcpcheck->comment = strdup(args[cur_arg + 1]);
5597 }
5598
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005599 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5600 }
5601 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005602 struct tcpcheck_rule *tcpcheck;
5603
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005604 if (!*(args[cur_arg + 1])) {
5605 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5606 file, linenum, args[0], args[1], ptr_arg);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005611 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612
5613 tcpcheck->action = TCPCHK_ACT_EXPECT;
5614 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5615 tcpcheck->string = strdup(args[cur_arg + 1]);
5616 tcpcheck->expect_regex = NULL;
5617 tcpcheck->inverse = inverse;
5618
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005619 /* tcpcheck comment */
5620 cur_arg += 2;
5621 if (strcmp(args[cur_arg], "comment") == 0) {
5622 if (!*args[cur_arg + 1]) {
5623 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5624 file, linenum, args[cur_arg + 1]);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628 tcpcheck->comment = strdup(args[cur_arg + 1]);
5629 }
5630
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005631 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5632 }
5633 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005634 struct tcpcheck_rule *tcpcheck;
5635
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005636 if (!*(args[cur_arg + 1])) {
5637 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5638 file, linenum, args[0], args[1], ptr_arg);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005642
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005643 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005644
5645 tcpcheck->action = TCPCHK_ACT_EXPECT;
5646 tcpcheck->string_len = 0;
5647 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005648 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5649 error = NULL;
5650 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5651 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5652 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5653 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657 tcpcheck->inverse = inverse;
5658
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005659 /* tcpcheck comment */
5660 cur_arg += 2;
5661 if (strcmp(args[cur_arg], "comment") == 0) {
5662 if (!*args[cur_arg + 1]) {
5663 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5664 file, linenum, args[cur_arg + 1]);
5665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
5668 tcpcheck->comment = strdup(args[cur_arg + 1]);
5669 }
5670
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005671 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5672 }
5673 else {
5674 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5675 file, linenum, args[0], args[1], ptr_arg);
5676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
5678 }
5679 }
5680 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005681 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
5684 }
5685 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005686 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005687 if (curproxy == &defproxy) {
5688 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005691 }
5692
Willy Tarreaub80c2302007-11-30 20:51:32 +01005693 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005695
5696 if (strcmp(args[1], "fail") == 0) {
5697 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005698 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005699 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5700 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005703 }
5704
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005705 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5706 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5707 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005710 }
5711 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5712 }
5713 else {
5714 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005717 }
5718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719#ifdef TPROXY
5720 else if (!strcmp(args[0], "transparent")) {
5721 /* enable transparent proxy connections */
5722 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005723 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 }
5726#endif
5727 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005728 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005730
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 if (*(args[1]) == 0) {
5732 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 }
5736 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005737 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005740 else if (!strcmp(args[0], "backlog")) { /* backlog */
5741 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005743
5744 if (*(args[1]) == 0) {
5745 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005748 }
5749 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005750 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5751 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005752 }
Willy Tarreau86034312006-12-29 00:10:33 +01005753 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005756
Willy Tarreau86034312006-12-29 00:10:33 +01005757 if (*(args[1]) == 0) {
5758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005761 }
5762 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005763 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5764 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5767 if (*(args[1]) == 0) {
5768 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005772 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5773 if (err) {
5774 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5775 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005778 }
5779 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005780 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
5783 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005784 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005785 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005786 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005787
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 if (curproxy == &defproxy) {
5789 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005793 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005795
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005796 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005797 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005798 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005799 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005800 goto out;
5801 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005802
5803 proto = protocol_by_family(sk->ss_family);
5804 if (!proto || !proto->connect) {
5805 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5806 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
5809 }
5810
5811 if (port1 != port2) {
5812 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5813 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005817
5818 if (!port1) {
5819 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5820 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005821 err_code |= ERR_ALERT | ERR_FATAL;
5822 goto out;
5823 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005824
William Lallemanddf1425a2015-04-28 20:17:49 +02005825 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5826 goto out;
5827
Willy Tarreaud5191e72010-02-09 20:50:45 +01005828 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005829 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830 }
5831 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005832 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005833 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005834
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005835 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5836 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005841 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005842 /**
5843 * The syntax for hash-type config element is
5844 * hash-type {map-based|consistent} [[<algo>] avalanche]
5845 *
5846 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5847 */
5848 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005849
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5851 err_code |= ERR_WARN;
5852
5853 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005854 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5855 }
5856 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005857 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5858 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005859 else if (strcmp(args[1], "avalanche") == 0) {
5860 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]);
5861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005863 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005864 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005865 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
5868 }
Bhaskar98634f02013-10-29 23:30:51 -04005869
5870 /* set the hash function to use */
5871 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005872 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005873 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005874
5875 /* if consistent with no argument, then avalanche modifier is also applied */
5876 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5877 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005878 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005879 /* set the hash function */
5880 if (!strcmp(args[2], "sdbm")) {
5881 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5882 }
5883 else if (!strcmp(args[2], "djb2")) {
5884 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005885 }
5886 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005887 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005888 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005889 else if (!strcmp(args[2], "crc32")) {
5890 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5891 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005892 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005893 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 -05005894 err_code |= ERR_ALERT | ERR_FATAL;
5895 goto out;
5896 }
5897
5898 /* set the hash modifier */
5899 if (!strcmp(args[3], "avalanche")) {
5900 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5901 }
5902 else if (*args[3]) {
5903 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005907 }
William Lallemanda73203e2012-03-12 12:48:57 +01005908 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005909 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5910 if (*(args[1]) == 0) {
5911 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
5914 }
5915 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5916 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5917 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
5920 }
5921 }
William Lallemanda73203e2012-03-12 12:48:57 +01005922 else if (strcmp(args[0], "unique-id-format") == 0) {
5923 if (!*(args[1])) {
5924 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5925 err_code |= ERR_ALERT | ERR_FATAL;
5926 goto out;
5927 }
William Lallemand3203ff42012-11-11 17:30:56 +01005928 if (*(args[2])) {
5929 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005933 free(curproxy->conf.uniqueid_format_string);
5934 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005935
Willy Tarreau62a61232013-04-12 18:13:46 +02005936 free(curproxy->conf.uif_file);
5937 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5938 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005939 }
William Lallemanda73203e2012-03-12 12:48:57 +01005940
5941 else if (strcmp(args[0], "unique-id-header") == 0) {
5942 if (!*(args[1])) {
5943 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5944 err_code |= ERR_ALERT | ERR_FATAL;
5945 goto out;
5946 }
5947 free(curproxy->header_unique_id);
5948 curproxy->header_unique_id = strdup(args[1]);
5949 }
5950
William Lallemand723b73a2012-02-08 16:37:49 +01005951 else if (strcmp(args[0], "log-format") == 0) {
5952 if (!*(args[1])) {
5953 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956 }
William Lallemand3203ff42012-11-11 17:30:56 +01005957 if (*(args[2])) {
5958 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
5961 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005962 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5963 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005964
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005965 if (curproxy->conf.logformat_string == default_http_log_format)
5966 oldlogformat = "option httplog";
5967 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5968 oldlogformat = "option tcplog";
5969 else if (curproxy->conf.logformat_string == clf_http_log_format)
5970 oldlogformat = "option httplog clf";
5971 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5972 file, linenum, oldlogformat);
5973 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005974 if (curproxy->conf.logformat_string != default_http_log_format &&
5975 curproxy->conf.logformat_string != default_tcp_log_format &&
5976 curproxy->conf.logformat_string != clf_http_log_format)
5977 free(curproxy->conf.logformat_string);
5978 curproxy->conf.logformat_string = strdup(args[1]);
5979
5980 free(curproxy->conf.lfs_file);
5981 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5982 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005983
5984 /* get a chance to improve log-format error reporting by
5985 * reporting the correct line-number when possible.
5986 */
5987 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5988 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5989 file, linenum, curproxy->id);
5990 err_code |= ERR_WARN;
5991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005993 else if (!strcmp(args[0], "log-format-sd")) {
5994 if (!*(args[1])) {
5995 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5996 err_code |= ERR_ALERT | ERR_FATAL;
5997 goto out;
5998 }
5999 if (*(args[2])) {
6000 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6001 err_code |= ERR_ALERT | ERR_FATAL;
6002 goto out;
6003 }
6004
6005 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6006 free(curproxy->conf.logformat_sd_string);
6007 curproxy->conf.logformat_sd_string = strdup(args[1]);
6008
6009 free(curproxy->conf.lfsd_file);
6010 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6011 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6012
6013 /* get a chance to improve log-format-sd error reporting by
6014 * reporting the correct line-number when possible.
6015 */
6016 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6017 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6018 file, linenum, curproxy->id);
6019 err_code |= ERR_WARN;
6020 }
6021 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006022 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6023 if (*(args[1]) == 0) {
6024 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006028 chunk_destroy(&curproxy->log_tag);
6029 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006030 }
William Lallemand0f99e342011-10-12 17:50:54 +02006031 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6032 /* delete previous herited or defined syslog servers */
6033 struct logsrv *back;
6034
6035 if (*(args[1]) != 0) {
6036 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6037 err_code |= ERR_ALERT | ERR_FATAL;
6038 goto out;
6039 }
6040
William Lallemand723b73a2012-02-08 16:37:49 +01006041 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6042 LIST_DEL(&tmplogsrv->list);
6043 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006044 }
6045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006046 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006047 struct logsrv *logsrv;
6048
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006050 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006051 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006052 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006053 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006054 LIST_INIT(&node->list);
6055 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 }
6058 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006059 struct sockaddr_storage *sk;
6060 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006061 int arg = 0;
6062 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006063
Vincent Bernat02779b62016-04-03 13:48:43 +02006064 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065
Willy Tarreau18324f52014-06-27 18:10:07 +02006066 /* just after the address, a length may be specified */
6067 if (strcmp(args[arg+2], "len") == 0) {
6068 len = atoi(args[arg+3]);
6069 if (len < 80 || len > 65535) {
6070 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6071 file, linenum, args[arg+3]);
6072 err_code |= ERR_ALERT | ERR_FATAL;
6073 goto out;
6074 }
6075 logsrv->maxlen = len;
6076
6077 /* skip these two args */
6078 arg += 2;
6079 }
6080 else
6081 logsrv->maxlen = MAX_SYSLOG_LEN;
6082
6083 if (logsrv->maxlen > global.max_syslog_len) {
6084 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006085 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6086 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6087 logline = my_realloc2(logline, global.max_syslog_len + 1);
6088 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006089 }
6090
Dragan Dosen1322d092015-09-22 16:05:32 +02006091 /* after the length, a format may be specified */
6092 if (strcmp(args[arg+2], "format") == 0) {
6093 logsrv->format = get_log_format(args[arg+3]);
6094 if (logsrv->format < 0) {
6095 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
6098 }
6099
6100 /* skip these two args */
6101 arg += 2;
6102 }
6103
William Lallemanddf1425a2015-04-28 20:17:49 +02006104 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6105 goto out;
6106
Willy Tarreau18324f52014-06-27 18:10:07 +02006107 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006108 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006109 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
6112
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114
William Lallemand0f99e342011-10-12 17:50:54 +02006115 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006116 if (*(args[arg+3])) {
6117 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006118 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006119 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 }
6124 }
6125
William Lallemand0f99e342011-10-12 17:50:54 +02006126 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006127 if (*(args[arg+4])) {
6128 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006129 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006130 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006134 }
6135 }
6136
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006137 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006138 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006139 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006141 goto out;
6142 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006143
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006144 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006145
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006146 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006147 if (port1 != port2) {
6148 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6149 file, linenum, args[0], args[1]);
6150 err_code |= ERR_ALERT | ERR_FATAL;
6151 goto out;
6152 }
6153
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006154 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006155 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
William Lallemand0f99e342011-10-12 17:50:54 +02006157
6158 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 }
6160 else {
6161 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6162 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006163 err_code |= ERR_ALERT | ERR_FATAL;
6164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 }
6166 }
6167 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006169 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006170 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006171 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006172
Willy Tarreau977b8e42006-12-29 14:19:17 +01006173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006175
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6178 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006182
6183 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006184 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6185 free(curproxy->conn_src.iface_name);
6186 curproxy->conn_src.iface_name = NULL;
6187 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006188
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006189 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006190 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006191 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006192 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006194 goto out;
6195 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006196
6197 proto = protocol_by_family(sk->ss_family);
6198 if (!proto || !proto->connect) {
6199 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006200 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
6203 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006204
6205 if (port1 != port2) {
6206 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6207 file, linenum, args[0], args[1]);
6208 err_code |= ERR_ALERT | ERR_FATAL;
6209 goto out;
6210 }
6211
Willy Tarreauef9a3602012-12-08 22:29:20 +01006212 curproxy->conn_src.source_addr = *sk;
6213 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006214
6215 cur_arg = 2;
6216 while (*(args[cur_arg])) {
6217 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006218#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006219 if (!*args[cur_arg + 1]) {
6220 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6221 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006224 }
6225
6226 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6228 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006229 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006230 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6231 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006232 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6233 char *name, *end;
6234
6235 name = args[cur_arg+1] + 7;
6236 while (isspace(*name))
6237 name++;
6238
6239 end = name;
6240 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6241 end++;
6242
Willy Tarreauef9a3602012-12-08 22:29:20 +01006243 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6244 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6245 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6246 curproxy->conn_src.bind_hdr_len = end - name;
6247 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6248 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6249 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006250
6251 /* now look for an occurrence number */
6252 while (isspace(*end))
6253 end++;
6254 if (*end == ',') {
6255 end++;
6256 name = end;
6257 if (*end == '-')
6258 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006259 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006260 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006261 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006262 }
6263
Willy Tarreauef9a3602012-12-08 22:29:20 +01006264 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006265 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6266 " occurrences values smaller than %d.\n",
6267 file, linenum, MAX_HDR_HISTORY);
6268 err_code |= ERR_ALERT | ERR_FATAL;
6269 goto out;
6270 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006271 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006272 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006273
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006274 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006275 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006276 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006277 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 goto out;
6280 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006281
6282 proto = protocol_by_family(sk->ss_family);
6283 if (!proto || !proto->connect) {
6284 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6285 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
6288 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006289
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006290 if (port1 != port2) {
6291 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6292 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
6295 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006296 curproxy->conn_src.tproxy_addr = *sk;
6297 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006298 }
6299 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300#else /* no TPROXY support */
6301 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006302 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= ERR_ALERT | ERR_FATAL;
6304 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006305#endif
6306 cur_arg += 2;
6307 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006308 }
6309
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006310 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6311#ifdef SO_BINDTODEVICE
6312 if (!*args[cur_arg + 1]) {
6313 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
6316 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006317 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006318 free(curproxy->conn_src.iface_name);
6319 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6320 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006321 global.last_checks |= LSTCHK_NETADM;
6322#else
6323 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6324 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006327#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006328 cur_arg += 2;
6329 continue;
6330 }
6331 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006332 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006333 err_code |= ERR_ALERT | ERR_FATAL;
6334 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006337 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6338 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6339 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006340 err_code |= ERR_ALERT | ERR_FATAL;
6341 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006345 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006347 err_code |= ERR_ALERT | ERR_FATAL;
6348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350
6351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006352 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006353 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
6357 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 }
6364 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006366 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
6371 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
6378 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006380 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006381 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006385 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006387 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006388 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006390 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399
6400 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006401 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006402 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006403 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
6406 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006408 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006409 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006415 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 }
6420 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006422 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006423 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006434 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006442 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006443
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 if (curproxy == &defproxy) {
6445 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006449 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006450 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 if (*(args[1]) == 0) {
6453 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006454 err_code |= ERR_ALERT | ERR_FATAL;
6455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006457
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006458 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006459 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6460 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6461 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006462 err_code |= ERR_ALERT | ERR_FATAL;
6463 goto out;
6464 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006465 err_code |= warnif_cond_conflicts(cond,
6466 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6467 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006468 }
6469 else if (*args[2]) {
6470 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6471 file, linenum, args[0], args[2]);
6472 err_code |= ERR_ALERT | ERR_FATAL;
6473 goto out;
6474 }
6475
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006476 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006477 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006478 wl->s = strdup(args[1]);
6479 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006480 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006489
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006492 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006498 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006499 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 }
6503 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006505 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006511 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6513 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006514 err_code |= ERR_ALERT | ERR_FATAL;
6515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
6517
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006519 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006520 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006526 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006527 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
6531 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006533 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
6538 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006539 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006540
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 if (curproxy == &defproxy) {
6542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006546 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006547 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 if (*(args[1]) == 0) {
6550 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006551 err_code |= ERR_ALERT | ERR_FATAL;
6552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 }
6554
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006556 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6557 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6558 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006559 err_code |= ERR_ALERT | ERR_FATAL;
6560 goto out;
6561 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006562 err_code |= warnif_cond_conflicts(cond,
6563 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6564 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006565 }
6566 else if (*args[2]) {
6567 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6568 file, linenum, args[0], args[2]);
6569 err_code |= ERR_ALERT | ERR_FATAL;
6570 goto out;
6571 }
6572
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006573 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006574 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006575 wl->s = strdup(args[1]);
6576 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
6578 else if (!strcmp(args[0], "errorloc") ||
6579 !strcmp(args[0], "errorloc302") ||
6580 !strcmp(args[0], "errorloc303")) { /* error location */
6581 int errnum, errlen;
6582 char *err;
6583
Willy Tarreau977b8e42006-12-29 14:19:17 +01006584 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006585 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006586
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006588 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006589 err_code |= ERR_ALERT | ERR_FATAL;
6590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591 }
6592
6593 errnum = atol(args[1]);
6594 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006595 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6596 err = malloc(errlen);
6597 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006599 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6600 err = malloc(errlen);
6601 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
6603
Willy Tarreau0f772532006-12-23 20:51:41 +01006604 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6605 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006606 chunk_destroy(&curproxy->errmsg[rc]);
6607 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006608 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006611
6612 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006613 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6614 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615 free(err);
6616 }
6617 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006618 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6619 int errnum, errlen, fd;
6620 char *err;
6621 struct stat stat;
6622
6623 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006624 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006625
6626 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006627 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006630 }
6631
6632 fd = open(args[2], O_RDONLY);
6633 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6634 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6635 file, linenum, args[2], args[1]);
6636 if (fd >= 0)
6637 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006640 }
6641
Willy Tarreau27a674e2009-08-17 07:23:33 +02006642 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006643 errlen = stat.st_size;
6644 } else {
6645 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006646 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006647 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006648 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006649 }
6650
6651 err = malloc(errlen); /* malloc() must succeed during parsing */
6652 errnum = read(fd, err, errlen);
6653 if (errnum != errlen) {
6654 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6655 file, linenum, args[2], args[1]);
6656 close(fd);
6657 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006658 err_code |= ERR_ALERT | ERR_FATAL;
6659 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006660 }
6661 close(fd);
6662
6663 errnum = atol(args[1]);
6664 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6665 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006666 chunk_destroy(&curproxy->errmsg[rc]);
6667 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006668 break;
6669 }
6670 }
6671
6672 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006673 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6674 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006675 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006676 free(err);
6677 }
6678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006679 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006680 struct cfg_kw_list *kwl;
6681 int index;
6682
6683 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6684 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6685 if (kwl->kw[index].section != CFG_LISTEN)
6686 continue;
6687 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6688 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006689 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006690 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006691 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006692 err_code |= ERR_ALERT | ERR_FATAL;
6693 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006694 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006695 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006696 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006697 err_code |= ERR_WARN;
6698 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006699 }
Willy Tarreau93893792009-07-23 13:19:11 +02006700 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006701 }
6702 }
6703 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006704
Willy Tarreau6daf3432008-01-22 16:44:08 +01006705 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006706 err_code |= ERR_ALERT | ERR_FATAL;
6707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708 }
Willy Tarreau93893792009-07-23 13:19:11 +02006709 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006710 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006711 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712}
6713
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006714int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006715cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6716{
6717#ifdef CONFIG_HAP_NS
6718 const char *err;
6719 const char *item = args[0];
6720
6721 if (!strcmp(item, "namespace_list")) {
6722 return 0;
6723 }
6724 else if (!strcmp(item, "namespace")) {
6725 size_t idx = 1;
6726 const char *current;
6727 while (*(current = args[idx++])) {
6728 err = invalid_char(current);
6729 if (err) {
6730 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6731 file, linenum, *err, item, current);
6732 return ERR_ALERT | ERR_FATAL;
6733 }
6734
6735 if (netns_store_lookup(current, strlen(current))) {
6736 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6737 file, linenum, current);
6738 return ERR_ALERT | ERR_FATAL;
6739 }
6740 if (!netns_store_insert(current)) {
6741 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6742 file, linenum, current);
6743 return ERR_ALERT | ERR_FATAL;
6744 }
6745 }
6746 }
6747
6748 return 0;
6749#else
6750 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6751 file, linenum);
6752 return ERR_ALERT | ERR_FATAL;
6753#endif
6754}
6755
6756int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006757cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6758{
6759
6760 int err_code = 0;
6761 const char *err;
6762
6763 if (!strcmp(args[0], "userlist")) { /* new userlist */
6764 struct userlist *newul;
6765
6766 if (!*args[1]) {
6767 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6768 file, linenum, args[0]);
6769 err_code |= ERR_ALERT | ERR_FATAL;
6770 goto out;
6771 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6773 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006774
6775 err = invalid_char(args[1]);
6776 if (err) {
6777 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6778 file, linenum, *err, args[0], args[1]);
6779 err_code |= ERR_ALERT | ERR_FATAL;
6780 goto out;
6781 }
6782
6783 for (newul = userlist; newul; newul = newul->next)
6784 if (!strcmp(newul->name, args[1])) {
6785 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6786 file, linenum, args[1]);
6787 err_code |= ERR_WARN;
6788 goto out;
6789 }
6790
Vincent Bernat02779b62016-04-03 13:48:43 +02006791 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 if (!newul) {
6793 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6794 err_code |= ERR_ALERT | ERR_ABORT;
6795 goto out;
6796 }
6797
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006798 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006799 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6801 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006802 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 goto out;
6804 }
6805
6806 newul->next = userlist;
6807 userlist = newul;
6808
6809 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006811 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813
6814 if (!*args[1]) {
6815 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6816 file, linenum, args[0]);
6817 err_code |= ERR_ALERT | ERR_FATAL;
6818 goto out;
6819 }
6820
6821 err = invalid_char(args[1]);
6822 if (err) {
6823 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6824 file, linenum, *err, args[0], args[1]);
6825 err_code |= ERR_ALERT | ERR_FATAL;
6826 goto out;
6827 }
6828
William Lallemand4ac9f542015-05-28 18:03:51 +02006829 if (!userlist)
6830 goto out;
6831
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006832 for (ag = userlist->groups; ag; ag = ag->next)
6833 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6835 file, linenum, args[1], userlist->name);
6836 err_code |= ERR_ALERT;
6837 goto out;
6838 }
6839
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006840 ag = calloc(1, sizeof(*ag));
6841 if (!ag) {
6842 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6843 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844 goto out;
6845 }
6846
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006847 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006848 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6850 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006851 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006852 goto out;
6853 }
6854
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 cur_arg = 2;
6856
6857 while (*args[cur_arg]) {
6858 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006859 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860 cur_arg += 2;
6861 continue;
6862 } else {
6863 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6864 file, linenum, args[0]);
6865 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006866 free(ag->groupusers);
6867 free(ag->name);
6868 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869 goto out;
6870 }
6871 }
6872
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006873 ag->next = userlist->groups;
6874 userlist->groups = ag;
6875
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006876 } else if (!strcmp(args[0], "user")) { /* new user */
6877 struct auth_users *newuser;
6878 int cur_arg;
6879
6880 if (!*args[1]) {
6881 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6882 file, linenum, args[0]);
6883 err_code |= ERR_ALERT | ERR_FATAL;
6884 goto out;
6885 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006886 if (!userlist)
6887 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888
6889 for (newuser = userlist->users; newuser; newuser = newuser->next)
6890 if (!strcmp(newuser->user, args[1])) {
6891 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6892 file, linenum, args[1], userlist->name);
6893 err_code |= ERR_ALERT;
6894 goto out;
6895 }
6896
Vincent Bernat02779b62016-04-03 13:48:43 +02006897 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898 if (!newuser) {
6899 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6900 err_code |= ERR_ALERT | ERR_ABORT;
6901 goto out;
6902 }
6903
6904 newuser->user = strdup(args[1]);
6905
6906 newuser->next = userlist->users;
6907 userlist->users = newuser;
6908
6909 cur_arg = 2;
6910
6911 while (*args[cur_arg]) {
6912 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006913#ifdef CONFIG_HAP_CRYPT
6914 if (!crypt("", args[cur_arg + 1])) {
6915 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6916 file, linenum, newuser->user);
6917 err_code |= ERR_ALERT | ERR_FATAL;
6918 goto out;
6919 }
6920#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006921 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6922 file, linenum);
6923 err_code |= ERR_ALERT;
6924#endif
6925 newuser->pass = strdup(args[cur_arg + 1]);
6926 cur_arg += 2;
6927 continue;
6928 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6929 newuser->pass = strdup(args[cur_arg + 1]);
6930 newuser->flags |= AU_O_INSECURE;
6931 cur_arg += 2;
6932 continue;
6933 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006934 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006935 cur_arg += 2;
6936 continue;
6937 } else {
6938 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6939 file, linenum, args[0]);
6940 err_code |= ERR_ALERT | ERR_FATAL;
6941 goto out;
6942 }
6943 }
6944 } else {
6945 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6946 err_code |= ERR_ALERT | ERR_FATAL;
6947 }
6948
6949out:
6950 return err_code;
6951}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952
Christopher Faulet79bdef32016-11-04 22:36:15 +01006953int
6954cfg_parse_scope(const char *file, int linenum, char *line)
6955{
6956 char *beg, *end, *scope = NULL;
6957 int err_code = 0;
6958 const char *err;
6959
6960 beg = line + 1;
6961 end = strchr(beg, ']');
6962
6963 /* Detect end of scope declaration */
6964 if (!end || end == beg) {
6965 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6966 file, linenum);
6967 err_code |= ERR_ALERT | ERR_FATAL;
6968 goto out;
6969 }
6970
6971 /* Get scope name and check its validity */
6972 scope = my_strndup(beg, end-beg);
6973 err = invalid_char(scope);
6974 if (err) {
6975 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6976 file, linenum, *err);
6977 err_code |= ERR_ALERT | ERR_ABORT;
6978 goto out;
6979 }
6980
6981 /* Be sure to have a scope declaration alone on its line */
6982 line = end+1;
6983 while (isspace((unsigned char)*line))
6984 line++;
6985 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6986 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6987 file, linenum, *line);
6988 err_code |= ERR_ALERT | ERR_ABORT;
6989 goto out;
6990 }
6991
6992 /* We have a valid scope declaration, save it */
6993 free(cfg_scope);
6994 cfg_scope = scope;
6995 scope = NULL;
6996
6997 out:
6998 free(scope);
6999 return err_code;
7000}
7001
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002/*
7003 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007004 * Returns the error code, 0 if OK, or any combination of :
7005 * - ERR_ABORT: must abort ASAP
7006 * - ERR_FATAL: we can continue parsing but not start the service
7007 * - ERR_WARN: a warning has been emitted
7008 * - ERR_ALERT: an alert has been emitted
7009 * Only the two first ones can stop processing, the two others are just
7010 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007012int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013{
William Lallemand64e84512015-05-12 14:25:37 +02007014 char *thisline;
7015 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 FILE *f;
7017 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007018 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007019 struct cfg_section *cs = NULL;
7020 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007021 int readbytes = 0;
7022
7023 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007024 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007025 return -1;
7026 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007027
David Carlier97880bb2016-04-08 10:35:26 +01007028 if ((f=fopen(file,"r")) == NULL) {
7029 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007030 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032
William Lallemandb2f07452015-05-12 14:27:13 +02007033next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007034 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007035 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007036 char *end;
7037 char *args[MAX_LINE_ARGS + 1];
7038 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007039 int dquote = 0; /* double quote */
7040 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007041
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 linenum++;
7043
7044 end = line + strlen(line);
7045
William Lallemand64e84512015-05-12 14:25:37 +02007046 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007047 /* Check if we reached the limit and the last char is not \n.
7048 * Watch out for the last line without the terminating '\n'!
7049 */
William Lallemand64e84512015-05-12 14:25:37 +02007050 char *newline;
7051 int newlinesize = linesize * 2;
7052
7053 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7054 if (newline == NULL) {
7055 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7056 file, linenum);
7057 err_code |= ERR_ALERT | ERR_FATAL;
7058 continue;
7059 }
7060
7061 readbytes = linesize - 1;
7062 linesize = newlinesize;
7063 thisline = newline;
7064 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007065 }
7066
William Lallemand64e84512015-05-12 14:25:37 +02007067 readbytes = 0;
7068
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007070 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007072
Christopher Faulet79bdef32016-11-04 22:36:15 +01007073
7074 if (*line == '[') {/* This is the begining if a scope */
7075 err_code |= cfg_parse_scope(file, linenum, line);
7076 goto next_line;
7077 }
7078
Willy Tarreaubaaee002006-06-26 02:48:02 +02007079 arg = 0;
7080 args[arg] = line;
7081
7082 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007083 if (*line == '"' && !squote) { /* double quote outside single quotes */
7084 if (dquote)
7085 dquote = 0;
7086 else
7087 dquote = 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 == '\'' && !dquote) { /* single quote outside double quotes */
7092 if (squote)
7093 squote = 0;
7094 else
7095 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007096 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007097 end--;
7098 }
7099 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7101 * C equivalent value. Other combinations left unchanged (eg: \1).
7102 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007103 int skip = 0;
7104 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7105 *line = line[1];
7106 skip = 1;
7107 }
7108 else if (line[1] == 'r') {
7109 *line = '\r';
7110 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 else if (line[1] == 'n') {
7113 *line = '\n';
7114 skip = 1;
7115 }
7116 else if (line[1] == 't') {
7117 *line = '\t';
7118 skip = 1;
7119 }
7120 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007121 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007122 unsigned char hex1, hex2;
7123 hex1 = toupper(line[2]) - '0';
7124 hex2 = toupper(line[3]) - '0';
7125 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7126 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7127 *line = (hex1<<4) + hex2;
7128 skip = 3;
7129 }
7130 else {
7131 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007132 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007134 } else if (line[1] == '"') {
7135 *line = '"';
7136 skip = 1;
7137 } else if (line[1] == '\'') {
7138 *line = '\'';
7139 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007140 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7141 *line = '$';
7142 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 }
7144 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007145 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 end -= skip;
7147 }
7148 line++;
7149 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007150 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151 /* end of string, end of loop */
7152 *line = 0;
7153 break;
7154 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007155 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007156 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007157 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007158 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 line++;
7160 args[++arg] = line;
7161 }
William Lallemandb2f07452015-05-12 14:27:13 +02007162 else if (dquote && *line == '$') {
7163 /* environment variables are evaluated inside double quotes */
7164 char *var_beg;
7165 char *var_end;
7166 char save_char;
7167 char *value;
7168 int val_len;
7169 int newlinesize;
7170 int braces = 0;
7171
7172 var_beg = line + 1;
7173 var_end = var_beg;
7174
7175 if (*var_beg == '{') {
7176 var_beg++;
7177 var_end++;
7178 braces = 1;
7179 }
7180
7181 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7182 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7183 err_code |= ERR_ALERT | ERR_FATAL;
7184 goto next_line; /* skip current line */
7185 }
7186
7187 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7188 var_end++;
7189
7190 save_char = *var_end;
7191 *var_end = '\0';
7192 value = getenv(var_beg);
7193 *var_end = save_char;
7194 val_len = value ? strlen(value) : 0;
7195
7196 if (braces) {
7197 if (*var_end == '}') {
7198 var_end++;
7199 braces = 0;
7200 } else {
7201 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7202 err_code |= ERR_ALERT | ERR_FATAL;
7203 goto next_line; /* skip current line */
7204 }
7205 }
7206
7207 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7208
7209 /* if not enough space in thisline */
7210 if (newlinesize > linesize) {
7211 char *newline;
7212
7213 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7214 if (newline == NULL) {
7215 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7216 err_code |= ERR_ALERT | ERR_FATAL;
7217 goto next_line; /* slip current line */
7218 }
7219 /* recompute pointers if realloc returns a new pointer */
7220 if (newline != thisline) {
7221 int i;
7222 int diff;
7223
7224 for (i = 0; i <= arg; i++) {
7225 diff = args[i] - thisline;
7226 args[i] = newline + diff;
7227 }
7228
7229 diff = var_end - thisline;
7230 var_end = newline + diff;
7231 diff = end - thisline;
7232 end = newline + diff;
7233 diff = line - thisline;
7234 line = newline + diff;
7235 thisline = newline;
7236 }
7237 linesize = newlinesize;
7238 }
7239
7240 /* insert value inside the line */
7241 memmove(line + val_len, var_end, end - var_end + 1);
7242 memcpy(line, value, val_len);
7243 end += val_len - (var_end - line);
7244 line += val_len;
7245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007246 else {
7247 line++;
7248 }
7249 }
William Lallemandb2f07452015-05-12 14:27:13 +02007250
William Lallemandf9873ba2015-05-05 17:37:14 +02007251 if (dquote) {
7252 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7253 err_code |= ERR_ALERT | ERR_FATAL;
7254 }
7255
7256 if (squote) {
7257 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7258 err_code |= ERR_ALERT | ERR_FATAL;
7259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260
7261 /* empty line */
7262 if (!**args)
7263 continue;
7264
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007265 if (*line) {
7266 /* we had to stop due to too many args.
7267 * Let's terminate the string, print the offending part then cut the
7268 * last arg.
7269 */
7270 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7271 line++;
7272 *line = '\0';
7273
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007274 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007275 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007276 err_code |= ERR_ALERT | ERR_FATAL;
7277 args[arg] = line;
7278 }
7279
Willy Tarreau540abe42007-05-02 20:50:16 +02007280 /* zero out remaining args and ensure that at least one entry
7281 * is zeroed out.
7282 */
7283 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007284 args[arg] = line;
7285 }
7286
Willy Tarreau3842f002009-06-14 11:39:52 +02007287 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007288 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007289 char *tmp;
7290
Willy Tarreau3842f002009-06-14 11:39:52 +02007291 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007292 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007293 for (arg=0; *args[arg+1]; arg++)
7294 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007295 *tmp = '\0'; // fix the next arg to \0
7296 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007297 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007298 else if (!strcmp(args[0], "default")) {
7299 kwm = KWM_DEF;
7300 for (arg=0; *args[arg+1]; arg++)
7301 args[arg] = args[arg+1]; // shift args after inversion
7302 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007303
William Lallemand0f99e342011-10-12 17:50:54 +02007304 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7305 strcmp(args[0], "log") != 0) {
7306 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007307 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007308 }
7309
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007310 /* detect section start */
7311 list_for_each_entry(ics, &sections, list) {
7312 if (strcmp(args[0], ics->section_name) == 0) {
7313 cursection = ics->section_name;
7314 cs = ics;
7315 break;
7316 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007317 }
7318
Willy Tarreaubaaee002006-06-26 02:48:02 +02007319 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007320 if (cs)
7321 err_code |= cs->section_parser(file, linenum, args, kwm);
7322 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007323 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007324 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007325 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007326
7327 if (err_code & ERR_ABORT)
7328 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007329 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007330 free(cfg_scope);
7331 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007332 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007333 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007334 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007335 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007336}
7337
Willy Tarreau64ab6072014-09-16 12:17:36 +02007338/* This function propagates processes from frontend <from> to backend <to> so
7339 * that it is always guaranteed that a backend pointed to by a frontend is
7340 * bound to all of its processes. After that, if the target is a "listen"
7341 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007342 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007343 * checked first to ensure that <to> is already bound to all processes of
7344 * <from>, there is no risk of looping and we ensure to follow the shortest
7345 * path to the destination.
7346 *
7347 * It is possible to set <to> to NULL for the first call so that the function
7348 * takes care of visiting the initial frontend in <from>.
7349 *
7350 * It is important to note that the function relies on the fact that all names
7351 * have already been resolved.
7352 */
7353void propagate_processes(struct proxy *from, struct proxy *to)
7354{
7355 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007356
7357 if (to) {
7358 /* check whether we need to go down */
7359 if (from->bind_proc &&
7360 (from->bind_proc & to->bind_proc) == from->bind_proc)
7361 return;
7362
7363 if (!from->bind_proc && !to->bind_proc)
7364 return;
7365
7366 to->bind_proc = from->bind_proc ?
7367 (to->bind_proc | from->bind_proc) : 0;
7368
7369 /* now propagate down */
7370 from = to;
7371 }
7372
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007373 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007374 return;
7375
Willy Tarreauf6b70012014-12-18 14:00:43 +01007376 if (from->state == PR_STSTOPPED)
7377 return;
7378
Willy Tarreau64ab6072014-09-16 12:17:36 +02007379 /* default_backend */
7380 if (from->defbe.be)
7381 propagate_processes(from, from->defbe.be);
7382
7383 /* use_backend */
7384 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007385 if (rule->dynamic)
7386 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007387 to = rule->be.backend;
7388 propagate_processes(from, to);
7389 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007390}
7391
Willy Tarreaubb925012009-07-23 13:36:36 +02007392/*
7393 * Returns the error code, 0 if OK, or any combination of :
7394 * - ERR_ABORT: must abort ASAP
7395 * - ERR_FATAL: we can continue parsing but not start the service
7396 * - ERR_WARN: a warning has been emitted
7397 * - ERR_ALERT: an alert has been emitted
7398 * Only the two first ones can stop processing, the two others are just
7399 * indicators.
7400 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007401int check_config_validity()
7402{
7403 int cfgerr = 0;
7404 struct proxy *curproxy = NULL;
7405 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007406 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007407 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007408 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007409 char *err;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007410 struct dns_resolvers *curr_resolvers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007411
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007412 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413 /*
7414 * Now, check for the integrity of all that we have collected.
7415 */
7416
7417 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007418 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007419
Willy Tarreau193b8c62012-11-22 00:17:38 +01007420 if (!global.tune.max_http_hdr)
7421 global.tune.max_http_hdr = MAX_HTTP_HDR;
7422
7423 if (!global.tune.cookie_len)
7424 global.tune.cookie_len = CAPTURE_LEN;
7425
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007426 if (!global.tune.requri_len)
7427 global.tune.requri_len = REQURI_LEN;
7428
Emeric Brun96fd9262017-07-05 13:33:16 +02007429 pool2_requri = create_pool("requri", global.tune.requri_len , MEM_F_SHARED);
7430
Willy Tarreau193b8c62012-11-22 00:17:38 +01007431 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7432
Baptiste Assmann201c07f2017-05-22 15:17:15 +02007433 /* allocate pool of resolution per resolvers */
7434 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
7435 if (dns_alloc_resolution_pool(curr_resolvers) != 0) {
7436 /* error message is already displayed by dns_alloc_resolution_pool() */
7437 err_code |= ERR_ALERT | ERR_ABORT;
7438 goto out;
7439 }
7440 }
7441
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007442 /* Post initialisation of the users and groups lists. */
7443 err_code = userlist_postinit();
7444 if (err_code != ERR_NONE)
7445 goto out;
7446
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007447 /* first, we will invert the proxy list order */
7448 curproxy = NULL;
7449 while (proxy) {
7450 struct proxy *next;
7451
7452 next = proxy->next;
7453 proxy->next = curproxy;
7454 curproxy = proxy;
7455 if (!next)
7456 break;
7457 proxy = next;
7458 }
7459
Willy Tarreau419ead82014-09-16 13:41:21 +02007460 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007461 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007462 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007463 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007464 struct act_rule *trule;
7465 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007466 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007467 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007468 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007469
Willy Tarreau050536d2012-10-04 08:47:34 +02007470 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007471 /* proxy ID not set, use automatic numbering with first
7472 * spare entry starting with next_pxid.
7473 */
7474 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7475 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7476 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007477 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007478 next_pxid++;
7479
Willy Tarreau55ea7572007-06-17 19:56:27 +02007480
Willy Tarreaubaaee002006-06-26 02:48:02 +02007481 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007482 /* ensure we don't keep listeners uselessly bound */
7483 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007484 free((void *)curproxy->table.peers.name);
7485 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007486 continue;
7487 }
7488
Willy Tarreau102df612014-05-07 23:56:38 +02007489 /* Check multi-process mode compatibility for the current proxy */
7490
7491 if (curproxy->bind_proc) {
7492 /* an explicit bind-process was specified, let's check how many
7493 * processes remain.
7494 */
David Carliere6c39412015-07-02 07:00:17 +00007495 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007496
7497 curproxy->bind_proc &= nbits(global.nbproc);
7498 if (!curproxy->bind_proc && nbproc == 1) {
7499 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);
7500 curproxy->bind_proc = 1;
7501 }
7502 else if (!curproxy->bind_proc && nbproc > 1) {
7503 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);
7504 curproxy->bind_proc = 0;
7505 }
7506 }
7507
Willy Tarreau3d209582014-05-09 17:06:11 +02007508 /* check and reduce the bind-proc of each listener */
7509 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7510 unsigned long mask;
7511
7512 if (!bind_conf->bind_proc)
7513 continue;
7514
7515 mask = nbits(global.nbproc);
7516 if (curproxy->bind_proc)
7517 mask &= curproxy->bind_proc;
7518 /* mask cannot be null here thanks to the previous checks */
7519
David Carliere6c39412015-07-02 07:00:17 +00007520 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007521 bind_conf->bind_proc &= mask;
7522
7523 if (!bind_conf->bind_proc && nbproc == 1) {
7524 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",
7525 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7526 bind_conf->bind_proc = mask & ~(mask - 1);
7527 }
7528 else if (!bind_conf->bind_proc && nbproc > 1) {
7529 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",
7530 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7531 bind_conf->bind_proc = 0;
7532 }
7533 }
7534
Willy Tarreauff01a212009-03-15 13:46:16 +01007535 switch (curproxy->mode) {
7536 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007537 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007539 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7540 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007541 cfgerr++;
7542 }
7543
7544 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007545 Warning("config : servers will be ignored for %s '%s'.\n",
7546 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007547 break;
7548
7549 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007550 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007551 break;
7552
7553 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007554 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007555 break;
7556 }
7557
Willy Tarreauf3934b82015-08-11 11:36:45 +02007558 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7559 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7560 proxy_type_str(curproxy), curproxy->id);
7561 err_code |= ERR_WARN;
7562 }
7563
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007564 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007565 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007566 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007567 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7568 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007569 cfgerr++;
7570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007571#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007572 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007573 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7574 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007575 cfgerr++;
7576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007577#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007578 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007579 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7580 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007581 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007582 }
7583 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007584 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007585 /* If no LB algo is set in a backend, and we're not in
7586 * transparent mode, dispatch mode nor proxy mode, we
7587 * want to use balance roundrobin by default.
7588 */
7589 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7590 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007591 }
7592 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007593
Willy Tarreau1620ec32011-08-06 17:05:02 +02007594 if (curproxy->options & PR_O_DISPATCH)
7595 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7596 else if (curproxy->options & PR_O_HTTP_PROXY)
7597 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7598 else if (curproxy->options & PR_O_TRANSP)
7599 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007600
Willy Tarreau1620ec32011-08-06 17:05:02 +02007601 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7602 if (curproxy->options & PR_O_DISABLE404) {
7603 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7604 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7605 err_code |= ERR_WARN;
7606 curproxy->options &= ~PR_O_DISABLE404;
7607 }
7608 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7609 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7610 "send-state", proxy_type_str(curproxy), curproxy->id);
7611 err_code |= ERR_WARN;
7612 curproxy->options &= ~PR_O2_CHK_SNDST;
7613 }
Willy Tarreauef781042010-01-27 11:53:01 +01007614 }
7615
Simon Horman98637e52014-06-20 12:30:16 +09007616 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7617 if (!global.external_check) {
7618 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7619 curproxy->id, "option external-check");
7620 cfgerr++;
7621 }
7622 if (!curproxy->check_command) {
7623 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7624 curproxy->id, "option external-check");
7625 cfgerr++;
7626 }
7627 }
7628
Simon Horman64e34162015-02-06 11:11:57 +09007629 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007630 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7631 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007632 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7633 "'email-alert myhostname', or 'email-alert to' "
7634 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007635 "to be present).\n",
7636 proxy_type_str(curproxy), curproxy->id);
7637 err_code |= ERR_WARN;
7638 free_email_alert(curproxy);
7639 }
7640 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007641 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007642 }
7643
Simon Horman98637e52014-06-20 12:30:16 +09007644 if (curproxy->check_command) {
7645 int clear = 0;
7646 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7647 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7648 "external-check command", proxy_type_str(curproxy), curproxy->id);
7649 err_code |= ERR_WARN;
7650 clear = 1;
7651 }
7652 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007653 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007654 curproxy->id, "external-check command");
7655 cfgerr++;
7656 }
7657 if (clear) {
7658 free(curproxy->check_command);
7659 curproxy->check_command = NULL;
7660 }
7661 }
7662
7663 if (curproxy->check_path) {
7664 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7665 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7666 "external-check path", proxy_type_str(curproxy), curproxy->id);
7667 err_code |= ERR_WARN;
7668 free(curproxy->check_path);
7669 curproxy->check_path = NULL;
7670 }
7671 }
7672
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007673 /* if a default backend was specified, let's find it */
7674 if (curproxy->defbe.name) {
7675 struct proxy *target;
7676
Willy Tarreauafb39922015-05-26 12:04:09 +02007677 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007678 if (!target) {
7679 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7680 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007681 cfgerr++;
7682 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007683 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7684 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007685 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007686 } else if (target->mode != curproxy->mode &&
7687 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7688
7689 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7690 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7691 curproxy->conf.file, curproxy->conf.line,
7692 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7693 target->conf.file, target->conf.line);
7694 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007695 } else {
7696 free(curproxy->defbe.name);
7697 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007698 /* Update tot_fe_maxconn for a further fullconn's computation */
7699 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007700 /* Emit a warning if this proxy also has some servers */
7701 if (curproxy->srv) {
7702 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7703 curproxy->id);
7704 err_code |= ERR_WARN;
7705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007706 }
7707 }
7708
Emeric Brun3f783572017-01-12 11:21:28 +01007709 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7710 /* Case of listen without default backend
7711 * The curproxy will be its own default backend
7712 * so we update tot_fe_maxconn for a further
7713 * fullconn's computation */
7714 curproxy->tot_fe_maxconn += curproxy->maxconn;
7715 }
7716
Willy Tarreau55ea7572007-06-17 19:56:27 +02007717 /* find the target proxy for 'use_backend' rules */
7718 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007720 struct logformat_node *node;
7721 char *pxname;
7722
7723 /* Try to parse the string as a log format expression. If the result
7724 * of the parsing is only one entry containing a simple string, then
7725 * it's a standard string corresponding to a static rule, thus the
7726 * parsing is cancelled and be.name is restored to be resolved.
7727 */
7728 pxname = rule->be.name;
7729 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007730 curproxy->conf.args.ctx = ARGC_UBK;
7731 curproxy->conf.args.file = rule->file;
7732 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007733 err = NULL;
7734 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7735 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7736 rule->file, rule->line, pxname, err);
7737 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007738 cfgerr++;
7739 continue;
7740 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007741 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7742
7743 if (!LIST_ISEMPTY(&rule->be.expr)) {
7744 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7745 rule->dynamic = 1;
7746 free(pxname);
7747 continue;
7748 }
7749 /* simple string: free the expression and fall back to static rule */
7750 free(node->arg);
7751 free(node);
7752 }
7753
7754 rule->dynamic = 0;
7755 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007756
Willy Tarreauafb39922015-05-26 12:04:09 +02007757 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007758 if (!target) {
7759 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7760 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007761 cfgerr++;
7762 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007763 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7764 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007765 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007766 } else if (target->mode != curproxy->mode &&
7767 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7768
7769 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7770 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7771 curproxy->conf.file, curproxy->conf.line,
7772 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7773 target->conf.file, target->conf.line);
7774 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007775 } else {
7776 free((void *)rule->be.name);
7777 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007778 /* For each target of switching rules, we update
7779 * their tot_fe_maxconn, except if a previous rule point
7780 * on the same backend or on the default backend */
7781 if (rule->be.backend != curproxy->defbe.be) {
7782 struct switching_rule *swrule;
7783
7784 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7785 if (rule == swrule) {
7786 target->tot_fe_maxconn += curproxy->maxconn;
7787 break;
7788 }
7789 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7790 /* there is multiple ref of this backend */
7791 break;
7792 }
7793 }
7794 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007795 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007796 }
7797
Willy Tarreau64ab6072014-09-16 12:17:36 +02007798 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007799 list_for_each_entry(srule, &curproxy->server_rules, list) {
7800 struct server *target = findserver(curproxy, srule->srv.name);
7801
7802 if (!target) {
7803 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7804 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7805 cfgerr++;
7806 continue;
7807 }
7808 free((void *)srule->srv.name);
7809 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007810 }
7811
Emeric Brunb982a3d2010-01-04 15:45:53 +01007812 /* find the target table for 'stick' rules */
7813 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7814 struct proxy *target;
7815
Emeric Brun1d33b292010-01-04 15:47:17 +01007816 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7817 if (mrule->flags & STK_IS_STORE)
7818 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7819
Emeric Brunb982a3d2010-01-04 15:45:53 +01007820 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007821 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007822 else
7823 target = curproxy;
7824
7825 if (!target) {
7826 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7827 curproxy->id, mrule->table.name);
7828 cfgerr++;
7829 }
7830 else if (target->table.size == 0) {
7831 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7832 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7833 cfgerr++;
7834 }
Willy Tarreau12785782012-04-27 21:37:17 +02007835 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7836 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007837 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7838 cfgerr++;
7839 }
7840 else {
7841 free((void *)mrule->table.name);
7842 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007843 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007844 }
7845 }
7846
7847 /* find the target table for 'store response' rules */
7848 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7849 struct proxy *target;
7850
Emeric Brun1d33b292010-01-04 15:47:17 +01007851 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7852
Emeric Brunb982a3d2010-01-04 15:45:53 +01007853 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007854 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007855 else
7856 target = curproxy;
7857
7858 if (!target) {
7859 Alert("Proxy '%s': unable to find store table '%s'.\n",
7860 curproxy->id, mrule->table.name);
7861 cfgerr++;
7862 }
7863 else if (target->table.size == 0) {
7864 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7865 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7866 cfgerr++;
7867 }
Willy Tarreau12785782012-04-27 21:37:17 +02007868 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7869 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007870 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7871 cfgerr++;
7872 }
7873 else {
7874 free((void *)mrule->table.name);
7875 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007876 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007877 }
7878 }
7879
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007880 /* find the target table for 'tcp-request' layer 4 rules */
7881 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7882 struct proxy *target;
7883
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007884 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007885 continue;
7886
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007887 if (trule->arg.trk_ctr.table.n)
7888 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007889 else
7890 target = curproxy;
7891
7892 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007893 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007894 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007895 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007896 cfgerr++;
7897 }
7898 else if (target->table.size == 0) {
7899 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007901 cfgerr++;
7902 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007903 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007904 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007906 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007907 cfgerr++;
7908 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007909 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007910 free(trule->arg.trk_ctr.table.n);
7911 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007912 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007913 * to pass a list of counters to track and allocate them right here using
7914 * stktable_alloc_data_type().
7915 */
7916 }
7917 }
7918
Willy Tarreau620408f2016-10-21 16:37:51 +02007919 /* find the target table for 'tcp-request' layer 5 rules */
7920 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7921 struct proxy *target;
7922
7923 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7924 continue;
7925
7926 if (trule->arg.trk_ctr.table.n)
7927 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7928 else
7929 target = curproxy;
7930
7931 if (!target) {
7932 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7933 curproxy->id, trule->arg.trk_ctr.table.n,
7934 tcp_trk_idx(trule->action));
7935 cfgerr++;
7936 }
7937 else if (target->table.size == 0) {
7938 Alert("Proxy '%s': table '%s' used but not configured.\n",
7939 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7940 cfgerr++;
7941 }
7942 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7943 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7944 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7945 tcp_trk_idx(trule->action));
7946 cfgerr++;
7947 }
7948 else {
7949 free(trule->arg.trk_ctr.table.n);
7950 trule->arg.trk_ctr.table.t = &target->table;
7951 /* Note: if we decide to enhance the track-sc syntax, we may be able
7952 * to pass a list of counters to track and allocate them right here using
7953 * stktable_alloc_data_type().
7954 */
7955 }
7956 }
7957
Willy Tarreaud1f96522010-08-03 19:34:32 +02007958 /* find the target table for 'tcp-request' layer 6 rules */
7959 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7960 struct proxy *target;
7961
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007962 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007963 continue;
7964
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 if (trule->arg.trk_ctr.table.n)
7966 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007967 else
7968 target = curproxy;
7969
7970 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007971 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007972 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007973 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007974 cfgerr++;
7975 }
7976 else if (target->table.size == 0) {
7977 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007978 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007979 cfgerr++;
7980 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007981 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007982 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007983 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007984 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007985 cfgerr++;
7986 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007987 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007988 free(trule->arg.trk_ctr.table.n);
7989 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007990 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007991 * to pass a list of counters to track and allocate them right here using
7992 * stktable_alloc_data_type().
7993 */
7994 }
7995 }
7996
Baptiste Assmanne9544932015-11-03 23:31:35 +01007997 /* parse http-request capture rules to ensure id really exists */
7998 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7999 if (hrqrule->action != ACT_CUSTOM ||
8000 hrqrule->action_ptr != http_action_req_capture_by_id)
8001 continue;
8002
8003 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8004 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8005 curproxy->id, hrqrule->arg.capid.idx);
8006 cfgerr++;
8007 }
8008 }
8009
8010 /* parse http-response capture rules to ensure id really exists */
8011 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8012 if (hrqrule->action != ACT_CUSTOM ||
8013 hrqrule->action_ptr != http_action_res_capture_by_id)
8014 continue;
8015
8016 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8017 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8018 curproxy->id, hrqrule->arg.capid.idx);
8019 cfgerr++;
8020 }
8021 }
8022
Willy Tarreau09448f72014-06-25 18:12:15 +02008023 /* find the target table for 'http-request' layer 7 rules */
8024 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8025 struct proxy *target;
8026
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008027 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008028 continue;
8029
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008030 if (hrqrule->arg.trk_ctr.table.n)
8031 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008032 else
8033 target = curproxy;
8034
8035 if (!target) {
8036 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008037 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008038 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008039 cfgerr++;
8040 }
8041 else if (target->table.size == 0) {
8042 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008043 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008044 cfgerr++;
8045 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008046 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008047 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008048 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008049 http_trk_idx(hrqrule->action));
8050 cfgerr++;
8051 }
8052 else {
8053 free(hrqrule->arg.trk_ctr.table.n);
8054 hrqrule->arg.trk_ctr.table.t = &target->table;
8055 /* Note: if we decide to enhance the track-sc syntax, we may be able
8056 * to pass a list of counters to track and allocate them right here using
8057 * stktable_alloc_data_type().
8058 */
8059 }
8060 }
8061
8062 /* find the target table for 'http-response' layer 7 rules */
8063 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8064 struct proxy *target;
8065
8066 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8067 continue;
8068
8069 if (hrqrule->arg.trk_ctr.table.n)
8070 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8071 else
8072 target = curproxy;
8073
8074 if (!target) {
8075 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8076 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8077 http_trk_idx(hrqrule->action));
8078 cfgerr++;
8079 }
8080 else if (target->table.size == 0) {
8081 Alert("Proxy '%s': table '%s' used but not configured.\n",
8082 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8083 cfgerr++;
8084 }
8085 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8086 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8087 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8088 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008089 cfgerr++;
8090 }
8091 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008092 free(hrqrule->arg.trk_ctr.table.n);
8093 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008094 /* Note: if we decide to enhance the track-sc syntax, we may be able
8095 * to pass a list of counters to track and allocate them right here using
8096 * stktable_alloc_data_type().
8097 */
8098 }
8099 }
8100
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008101 /* move any "block" rules at the beginning of the http-request rules */
8102 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8103 /* insert block_rules into http_req_rules at the beginning */
8104 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8105 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8106 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8107 curproxy->http_req_rules.n = curproxy->block_rules.n;
8108 LIST_INIT(&curproxy->block_rules);
8109 }
8110
Emeric Brun32da3c42010-09-23 18:39:19 +02008111 if (curproxy->table.peers.name) {
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008112 struct peers *curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008113
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02008114 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Emeric Brun32da3c42010-09-23 18:39:19 +02008115 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8116 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008117 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008118 break;
8119 }
8120 }
8121
8122 if (!curpeers) {
8123 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8124 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008125 free((void *)curproxy->table.peers.name);
8126 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008127 cfgerr++;
8128 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008129 else if (curpeers->state == PR_STSTOPPED) {
8130 /* silently disable this peers section */
8131 curproxy->table.peers.p = NULL;
8132 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008133 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008134 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8135 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008136 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008137 cfgerr++;
8138 }
8139 }
8140
Simon Horman9dc49962015-01-30 11:22:59 +09008141
8142 if (curproxy->email_alert.mailers.name) {
8143 struct mailers *curmailers = mailers;
8144
8145 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8146 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8147 free(curproxy->email_alert.mailers.name);
8148 curproxy->email_alert.mailers.m = curmailers;
8149 curmailers->users++;
8150 break;
8151 }
8152 }
8153
8154 if (!curmailers) {
8155 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8156 curproxy->id, curproxy->email_alert.mailers.name);
8157 free_email_alert(curproxy);
8158 cfgerr++;
8159 }
8160 }
8161
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008162 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008163 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008164 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8165 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8166 "proxy", curproxy->id);
8167 cfgerr++;
8168 goto out_uri_auth_compat;
8169 }
8170
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008171 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008172 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008173 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008174 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008175
Willy Tarreau95fa4692010-02-01 13:05:50 +01008176 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8177 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008178
8179 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008180 uri_auth_compat_req[i++] = "realm";
8181 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8182 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008183
Willy Tarreau95fa4692010-02-01 13:05:50 +01008184 uri_auth_compat_req[i++] = "unless";
8185 uri_auth_compat_req[i++] = "{";
8186 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8187 uri_auth_compat_req[i++] = "}";
8188 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008189
Willy Tarreauff011f22011-01-06 17:51:27 +01008190 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8191 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008192 cfgerr++;
8193 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008194 }
8195
Willy Tarreauff011f22011-01-06 17:51:27 +01008196 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008197
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008198 if (curproxy->uri_auth->auth_realm) {
8199 free(curproxy->uri_auth->auth_realm);
8200 curproxy->uri_auth->auth_realm = NULL;
8201 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008202
8203 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008204 }
8205out_uri_auth_compat:
8206
Dragan Dosen43885c72015-10-01 13:18:13 +02008207 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008208 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008209 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8210 if (!curproxy->conf.logformat_sd_string) {
8211 /* set the default logformat_sd_string */
8212 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8213 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008214 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008215 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008216 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008217
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008218 /* compile the log format */
8219 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008220 if (curproxy->conf.logformat_string != default_http_log_format &&
8221 curproxy->conf.logformat_string != default_tcp_log_format &&
8222 curproxy->conf.logformat_string != clf_http_log_format)
8223 free(curproxy->conf.logformat_string);
8224 curproxy->conf.logformat_string = NULL;
8225 free(curproxy->conf.lfs_file);
8226 curproxy->conf.lfs_file = NULL;
8227 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008228
8229 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8230 free(curproxy->conf.logformat_sd_string);
8231 curproxy->conf.logformat_sd_string = NULL;
8232 free(curproxy->conf.lfsd_file);
8233 curproxy->conf.lfsd_file = NULL;
8234 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008235 }
8236
Willy Tarreau62a61232013-04-12 18:13:46 +02008237 if (curproxy->conf.logformat_string) {
8238 curproxy->conf.args.ctx = ARGC_LOG;
8239 curproxy->conf.args.file = curproxy->conf.lfs_file;
8240 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008241 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008242 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008243 SMP_VAL_FE_LOG_END, &err)) {
8244 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8245 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8246 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008247 cfgerr++;
8248 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008249 curproxy->conf.args.file = NULL;
8250 curproxy->conf.args.line = 0;
8251 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008252
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008253 if (curproxy->conf.logformat_sd_string) {
8254 curproxy->conf.args.ctx = ARGC_LOGSD;
8255 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8256 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008257 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008258 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 +01008259 SMP_VAL_FE_LOG_END, &err)) {
8260 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8261 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8262 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008263 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008264 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8265 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8266 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8267 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008268 cfgerr++;
8269 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008270 curproxy->conf.args.file = NULL;
8271 curproxy->conf.args.line = 0;
8272 }
8273
Willy Tarreau62a61232013-04-12 18:13:46 +02008274 if (curproxy->conf.uniqueid_format_string) {
8275 curproxy->conf.args.ctx = ARGC_UIF;
8276 curproxy->conf.args.file = curproxy->conf.uif_file;
8277 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008278 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008279 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 +01008280 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8281 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8282 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8283 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008284 cfgerr++;
8285 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008286 curproxy->conf.args.file = NULL;
8287 curproxy->conf.args.line = 0;
8288 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008289
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008290 /* only now we can check if some args remain unresolved.
8291 * This must be done after the users and groups resolution.
8292 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008293 cfgerr += smp_resolve_args(curproxy);
8294 if (!cfgerr)
8295 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008296
Willy Tarreau2738a142006-07-08 17:28:09 +02008297 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008298 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008299 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008300 (!curproxy->timeout.connect ||
8301 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008302 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008303 " | While not properly invalid, you will certainly encounter various problems\n"
8304 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008305 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008306 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008307 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008308 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008309
Willy Tarreau1fa31262007-12-03 00:36:16 +01008310 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8311 * We must still support older configurations, so let's find out whether those
8312 * parameters have been set or must be copied from contimeouts.
8313 */
8314 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008315 if (!curproxy->timeout.tarpit ||
8316 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008317 /* tarpit timeout not set. We search in the following order:
8318 * default.tarpit, curr.connect, default.connect.
8319 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008320 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008321 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008322 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008323 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008324 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008325 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008326 }
8327 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008328 (!curproxy->timeout.queue ||
8329 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008330 /* queue timeout not set. We search in the following order:
8331 * default.queue, curr.connect, default.connect.
8332 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008333 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008334 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008335 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008336 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008337 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008338 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008339 }
8340 }
8341
Willy Tarreau1620ec32011-08-06 17:05:02 +02008342 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008343 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008344 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008345 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008346 }
8347
Willy Tarreau215663d2014-06-13 18:30:23 +02008348 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8349 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8350 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8351 proxy_type_str(curproxy), curproxy->id);
8352 err_code |= ERR_WARN;
8353 }
8354
Willy Tarreau193b8c62012-11-22 00:17:38 +01008355 /* ensure that cookie capture length is not too large */
8356 if (curproxy->capture_len >= global.tune.cookie_len) {
8357 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8358 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8359 err_code |= ERR_WARN;
8360 curproxy->capture_len = global.tune.cookie_len - 1;
8361 }
8362
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008363 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008364 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008365 curproxy->req_cap_pool = create_pool("ptrcap",
8366 curproxy->nb_req_cap * sizeof(char *),
8367 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008368 }
8369
8370 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008371 curproxy->rsp_cap_pool = create_pool("ptrcap",
8372 curproxy->nb_rsp_cap * sizeof(char *),
8373 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008374 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008375
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008376 switch (curproxy->load_server_state_from_file) {
8377 case PR_SRV_STATE_FILE_UNSPEC:
8378 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8379 break;
8380 case PR_SRV_STATE_FILE_GLOBAL:
8381 if (!global.server_state_file) {
8382 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",
8383 curproxy->id);
8384 err_code |= ERR_WARN;
8385 }
8386 break;
8387 }
8388
Willy Tarreaubaaee002006-06-26 02:48:02 +02008389 /* first, we will invert the servers list order */
8390 newsrv = NULL;
8391 while (curproxy->srv) {
8392 struct server *next;
8393
8394 next = curproxy->srv->next;
8395 curproxy->srv->next = newsrv;
8396 newsrv = curproxy->srv;
8397 if (!next)
8398 break;
8399 curproxy->srv = next;
8400 }
8401
Willy Tarreau17edc812014-01-03 12:14:34 +01008402 /* Check that no server name conflicts. This causes trouble in the stats.
8403 * We only emit a warning for the first conflict affecting each server,
8404 * in order to avoid combinatory explosion if all servers have the same
8405 * name. We do that only for servers which do not have an explicit ID,
8406 * because these IDs were made also for distinguishing them and we don't
8407 * want to annoy people who correctly manage them.
8408 */
8409 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8410 struct server *other_srv;
8411
8412 if (newsrv->puid)
8413 continue;
8414
8415 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8416 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8417 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8418 newsrv->conf.file, newsrv->conf.line,
8419 proxy_type_str(curproxy), curproxy->id,
8420 newsrv->id, other_srv->conf.line);
8421 break;
8422 }
8423 }
8424 }
8425
Willy Tarreaudd701652010-05-25 23:03:02 +02008426 /* assign automatic UIDs to servers which don't have one yet */
8427 next_id = 1;
8428 newsrv = curproxy->srv;
8429 while (newsrv != NULL) {
8430 if (!newsrv->puid) {
8431 /* server ID not set, use automatic numbering with first
8432 * spare entry starting with next_svid.
8433 */
8434 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8435 newsrv->conf.id.key = newsrv->puid = next_id;
8436 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8437 }
8438 next_id++;
8439 newsrv = newsrv->next;
8440 }
8441
Willy Tarreau20697042007-11-15 23:26:18 +01008442 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008443 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008444
Willy Tarreau62c3be22012-01-20 13:12:32 +01008445 /*
8446 * If this server supports a maxconn parameter, it needs a dedicated
8447 * tasks to fill the emptied slots when a connection leaves.
8448 * Also, resolve deferred tracking dependency if needed.
8449 */
8450 newsrv = curproxy->srv;
8451 while (newsrv != NULL) {
8452 if (newsrv->minconn > newsrv->maxconn) {
8453 /* Only 'minconn' was specified, or it was higher than or equal
8454 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8455 * this will avoid further useless expensive computations.
8456 */
8457 newsrv->maxconn = newsrv->minconn;
8458 } else if (newsrv->maxconn && !newsrv->minconn) {
8459 /* minconn was not specified, so we set it to maxconn */
8460 newsrv->minconn = newsrv->maxconn;
8461 }
8462
Willy Tarreau17d45382016-12-22 21:16:08 +01008463 /* this will also properly set the transport layer for prod and checks */
8464 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8465 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8466 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8467 }
Emeric Brun94324a42012-10-11 14:00:19 +02008468
Willy Tarreau2f075e92013-12-03 11:11:34 +01008469 /* set the check type on the server */
8470 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8471
Willy Tarreau62c3be22012-01-20 13:12:32 +01008472 if (newsrv->trackit) {
8473 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008474 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008475 char *pname, *sname;
8476
8477 pname = newsrv->trackit;
8478 sname = strrchr(pname, '/');
8479
8480 if (sname)
8481 *sname++ = '\0';
8482 else {
8483 sname = pname;
8484 pname = NULL;
8485 }
8486
8487 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008488 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008489 if (!px) {
8490 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8491 proxy_type_str(curproxy), curproxy->id,
8492 newsrv->id, pname);
8493 cfgerr++;
8494 goto next_srv;
8495 }
8496 } else
8497 px = curproxy;
8498
8499 srv = findserver(px, sname);
8500 if (!srv) {
8501 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8502 proxy_type_str(curproxy), curproxy->id,
8503 newsrv->id, sname);
8504 cfgerr++;
8505 goto next_srv;
8506 }
8507
Willy Tarreau32091232014-05-16 13:52:00 +02008508 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8509 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8510 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008511 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008512 "tracking as it does not have any check nor agent enabled.\n",
8513 proxy_type_str(curproxy), curproxy->id,
8514 newsrv->id, px->id, srv->id);
8515 cfgerr++;
8516 goto next_srv;
8517 }
8518
8519 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8520
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008521 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008522 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8523 "belongs to a tracking chain looping back to %s/%s.\n",
8524 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008525 newsrv->id, px->id, srv->id, px->id,
8526 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008527 cfgerr++;
8528 goto next_srv;
8529 }
8530
8531 if (curproxy != px &&
8532 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8533 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8534 "tracking: disable-on-404 option inconsistency.\n",
8535 proxy_type_str(curproxy), curproxy->id,
8536 newsrv->id, px->id, srv->id);
8537 cfgerr++;
8538 goto next_srv;
8539 }
8540
Willy Tarreau62c3be22012-01-20 13:12:32 +01008541 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008542 newsrv->tracknext = srv->trackers;
8543 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008544
8545 free(newsrv->trackit);
8546 newsrv->trackit = NULL;
8547 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008548
8549 /*
8550 * resolve server's resolvers name and update the resolvers pointer
8551 * accordingly
8552 */
8553 if (newsrv->resolvers_id) {
8554 struct dns_resolvers *curr_resolvers;
8555 int found;
8556
8557 found = 0;
8558 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8559 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8560 found = 1;
8561 break;
8562 }
8563 }
8564
8565 if (!found) {
8566 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8567 proxy_type_str(curproxy), curproxy->id,
8568 newsrv->id, newsrv->resolvers_id);
8569 cfgerr++;
8570 } else {
Olivier Houchard8da5f982017-08-04 18:35:36 +02008571 if (newsrv->srvrq) {
8572 if (!newsrv->srvrq->resolvers) {
8573 newsrv->srvrq->resolvers = curr_resolvers;
8574 if (dns_link_resolution(newsrv->srvrq,
8575 OBJ_TYPE_SRVRQ, NULL) != 0) {
8576 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8577 proxy_type_str(curproxy), curproxy->id,
8578 newsrv->id);
8579 cfgerr++;
8580 }
8581 }
8582
8583 }
8584 if (newsrv->srvrq || newsrv->hostname_dn) {
Baptiste Assmann42746372017-05-03 12:12:02 +02008585 newsrv->resolvers = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02008586 if (dns_link_resolution(newsrv, OBJ_TYPE_SERVER, NULL) != 0) {
8587 Alert("config : %s '%s', server '%s': unable to set DNS resolution\n",
8588 proxy_type_str(curproxy), curproxy->id,
8589 newsrv->id);
8590 cfgerr++;
8591 }
8592 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008593 }
8594 }
8595 else {
8596 /* if no resolvers section associated to this server
8597 * we can clean up the associated resolution structure
8598 */
8599 if (newsrv->resolution) {
8600 free(newsrv->resolution->hostname_dn);
8601 newsrv->resolution->hostname_dn = NULL;
8602 free(newsrv->resolution);
8603 newsrv->resolution = NULL;
8604 }
8605 }
8606
Willy Tarreau62c3be22012-01-20 13:12:32 +01008607 next_srv:
8608 newsrv = newsrv->next;
8609 }
8610
Olivier Houchard4e694042017-03-14 20:01:29 +01008611 /*
8612 * Try to generate dynamic cookies for servers now.
8613 * It couldn't be done earlier, since at the time we parsed
8614 * the server line, we may not have known yet that we
8615 * should use dynamic cookies, or the secret key may not
8616 * have been provided yet.
8617 */
8618 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8619 newsrv = curproxy->srv;
8620 while (newsrv != NULL) {
8621 srv_set_dyncookie(newsrv);
8622 newsrv = newsrv->next;
8623 }
8624
8625 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008626 /* We have to initialize the server lookup mechanism depending
8627 * on what LB algorithm was choosen.
8628 */
8629
8630 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8631 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8632 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008633 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8634 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8635 init_server_map(curproxy);
8636 } else {
8637 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8638 fwrr_init_server_groups(curproxy);
8639 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008640 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008641
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008642 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008643 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8644 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8645 fwlc_init_server_tree(curproxy);
8646 } else {
8647 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8648 fas_init_server_tree(curproxy);
8649 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008650 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008651
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008652 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008653 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8654 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8655 chash_init_server_tree(curproxy);
8656 } else {
8657 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8658 init_server_map(curproxy);
8659 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008660 break;
8661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008662
8663 if (curproxy->options & PR_O_LOGASAP)
8664 curproxy->to_log &= ~LW_BYTES;
8665
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008666 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008667 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8668 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008669 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8670 proxy_type_str(curproxy), curproxy->id);
8671 err_code |= ERR_WARN;
8672 }
8673
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008674 if (curproxy->mode != PR_MODE_HTTP) {
8675 int optnum;
8676
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008677 if (curproxy->uri_auth) {
8678 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8679 proxy_type_str(curproxy), curproxy->id);
8680 err_code |= ERR_WARN;
8681 curproxy->uri_auth = NULL;
8682 }
8683
Willy Tarreaude7dc882017-03-10 11:49:21 +01008684 if (curproxy->capture_name) {
8685 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8686 proxy_type_str(curproxy), curproxy->id);
8687 err_code |= ERR_WARN;
8688 }
8689
8690 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8691 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8692 proxy_type_str(curproxy), curproxy->id);
8693 err_code |= ERR_WARN;
8694 }
8695
8696 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8697 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8698 proxy_type_str(curproxy), curproxy->id);
8699 err_code |= ERR_WARN;
8700 }
8701
8702 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8703 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8704 proxy_type_str(curproxy), curproxy->id);
8705 err_code |= ERR_WARN;
8706 }
8707
8708 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8709 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8710 proxy_type_str(curproxy), curproxy->id);
8711 err_code |= ERR_WARN;
8712 }
8713
Willy Tarreau87cf5142011-08-19 22:57:24 +02008714 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008715 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8716 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8717 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008718 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008719 }
8720
8721 if (curproxy->options & PR_O_ORGTO) {
8722 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8723 "originalto", proxy_type_str(curproxy), curproxy->id);
8724 err_code |= ERR_WARN;
8725 curproxy->options &= ~PR_O_ORGTO;
8726 }
8727
8728 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8729 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8730 (curproxy->cap & cfg_opts[optnum].cap) &&
8731 (curproxy->options & cfg_opts[optnum].val)) {
8732 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8733 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8734 err_code |= ERR_WARN;
8735 curproxy->options &= ~cfg_opts[optnum].val;
8736 }
8737 }
8738
8739 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8740 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8741 (curproxy->cap & cfg_opts2[optnum].cap) &&
8742 (curproxy->options2 & cfg_opts2[optnum].val)) {
8743 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8744 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8745 err_code |= ERR_WARN;
8746 curproxy->options2 &= ~cfg_opts2[optnum].val;
8747 }
8748 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008749
Willy Tarreau29fbe512015-08-20 19:35:14 +02008750#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008751 if (curproxy->conn_src.bind_hdr_occ) {
8752 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008753 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008754 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008755 err_code |= ERR_WARN;
8756 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008757#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008758 }
8759
Willy Tarreaubaaee002006-06-26 02:48:02 +02008760 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008761 * ensure that we're not cross-dressing a TCP server into HTTP.
8762 */
8763 newsrv = curproxy->srv;
8764 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008765 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008766 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8767 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008768 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008769 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008770
Willy Tarreau0cec3312011-10-31 13:49:26 +01008771 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8772 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8773 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8774 err_code |= ERR_WARN;
8775 }
8776
Willy Tarreauc93cd162014-05-13 15:54:22 +02008777 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008778 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8779 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8780 err_code |= ERR_WARN;
8781 }
8782
Willy Tarreau29fbe512015-08-20 19:35:14 +02008783#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008784 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8785 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008786 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 +01008787 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008788 err_code |= ERR_WARN;
8789 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008790#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008791
8792 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8793 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8794 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8795 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8796 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8797 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",
8798 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8799 err_code |= ERR_WARN;
8800 }
8801
8802
8803 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8804 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",
8805 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8806 err_code |= ERR_WARN;
8807 }
8808 }
8809
Willy Tarreau21d2af32008-02-14 20:25:24 +01008810 newsrv = newsrv->next;
8811 }
8812
Willy Tarreaue42bd962014-09-16 16:21:19 +02008813 /* check if we have a frontend with "tcp-request content" looking at L7
8814 * with no inspect-delay
8815 */
8816 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8817 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008818 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008819 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008820 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008821 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008822 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008823 break;
8824 }
8825
8826 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8827 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8828 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8829 " This means that these rules will randomly find their contents. This can be fixed by"
8830 " setting the tcp-request inspect-delay.\n",
8831 proxy_type_str(curproxy), curproxy->id);
8832 err_code |= ERR_WARN;
8833 }
8834 }
8835
Christopher Fauletd7c91962015-04-30 11:48:27 +02008836 /* Check filter configuration, if any */
8837 cfgerr += flt_check(curproxy);
8838
Willy Tarreauc1a21672009-08-16 22:37:44 +02008839 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008840 if (!curproxy->accept)
8841 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008842
Willy Tarreauc1a21672009-08-16 22:37:44 +02008843 if (curproxy->tcp_req.inspect_delay ||
8844 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008845 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008846
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008847 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008848 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008849 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008850 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008851
8852 /* both TCP and HTTP must check switching rules */
8853 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008854
8855 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008856 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008857 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8858 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 +01008859 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008860 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8861 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008862 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008863 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008864 }
8865
8866 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008867 if (curproxy->tcp_req.inspect_delay ||
8868 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8869 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8870
Emeric Brun97679e72010-09-23 17:56:44 +02008871 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8872 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8873
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008874 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008875 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008876 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008877 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008878
8879 /* If the backend does requires RDP cookie persistence, we have to
8880 * enable the corresponding analyser.
8881 */
8882 if (curproxy->options2 & PR_O2_RDPC_PRST)
8883 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008884
8885 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008886 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008887 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8888 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 +01008889 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008890 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8891 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008892 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008893 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008894 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008895 }
8896
8897 /***********************************************************/
8898 /* At this point, target names have already been resolved. */
8899 /***********************************************************/
8900
8901 /* Check multi-process mode compatibility */
8902
8903 if (global.nbproc > 1 && global.stats_fe) {
8904 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8905 unsigned long mask;
8906
8907 mask = nbits(global.nbproc);
8908 if (global.stats_fe->bind_proc)
8909 mask &= global.stats_fe->bind_proc;
8910
8911 if (bind_conf->bind_proc)
8912 mask &= bind_conf->bind_proc;
8913
8914 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008915 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008916 break;
8917 }
8918 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8919 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");
8920 }
8921 }
8922
8923 /* Make each frontend inherit bind-process from its listeners when not specified. */
8924 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8925 if (curproxy->bind_proc)
8926 continue;
8927
8928 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8929 unsigned long mask;
8930
Willy Tarreaue428b082015-05-04 21:57:58 +02008931 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008932 curproxy->bind_proc |= mask;
8933 }
8934
8935 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008936 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008937 }
8938
8939 if (global.stats_fe) {
8940 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8941 unsigned long mask;
8942
Cyril Bonté06181952016-02-24 00:14:54 +01008943 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008944 global.stats_fe->bind_proc |= mask;
8945 }
8946 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008947 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008948 }
8949
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008950 /* propagate bindings from frontends to backends. Don't do it if there
8951 * are any fatal errors as we must not call it with unresolved proxies.
8952 */
8953 if (!cfgerr) {
8954 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8955 if (curproxy->cap & PR_CAP_FE)
8956 propagate_processes(curproxy, NULL);
8957 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008958 }
8959
8960 /* Bind each unbound backend to all processes when not specified. */
8961 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8962 if (curproxy->bind_proc)
8963 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008964 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008965 }
8966
8967 /*******************************************************/
8968 /* At this step, all proxies have a non-null bind_proc */
8969 /*******************************************************/
8970
8971 /* perform the final checks before creating tasks */
8972
8973 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8974 struct listener *listener;
8975 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008976
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008977 /* Configure SSL for each bind line.
8978 * Note: if configuration fails at some point, the ->ctx member
8979 * remains NULL so that listeners can later detach.
8980 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008981 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008982 if (bind_conf->xprt->prepare_bind_conf &&
8983 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008984 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008985 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008986
Willy Tarreaue6b98942007-10-29 01:09:36 +01008987 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008988 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008989 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008990 int nbproc;
8991
8992 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008993 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008994 nbits(global.nbproc));
8995
8996 if (!nbproc) /* no intersection between listener and frontend */
8997 nbproc = 1;
8998
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008999 if (!listener->luid) {
9000 /* listener ID not set, use automatic numbering with first
9001 * spare entry starting with next_luid.
9002 */
9003 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
9004 listener->conf.id.key = listener->luid = next_id;
9005 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009006 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01009007 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009008
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009009 /* enable separate counters */
9010 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01009011 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009012 if (!listener->name)
9013 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009014 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009015
Willy Tarreaue6b98942007-10-29 01:09:36 +01009016 if (curproxy->options & PR_O_TCP_NOLING)
9017 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009018 if (!listener->maxconn)
9019 listener->maxconn = curproxy->maxconn;
9020 if (!listener->backlog)
9021 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009022 if (!listener->maxaccept)
9023 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9024
9025 /* we want to have an optimal behaviour on single process mode to
9026 * maximize the work at once, but in multi-process we want to keep
9027 * some fairness between processes, so we target half of the max
9028 * number of events to be balanced over all the processes the proxy
9029 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9030 * used to disable the limit.
9031 */
9032 if (listener->maxaccept > 0) {
9033 if (nbproc > 1)
9034 listener->maxaccept = (listener->maxaccept + 1) / 2;
9035 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9036 }
9037
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009038 listener->accept = session_accept_fd;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009039 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009040 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009041
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009042 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009043 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009044
Willy Tarreau620408f2016-10-21 16:37:51 +02009045 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9046 listener->options |= LI_O_TCP_L5_RULES;
9047
Willy Tarreaude3041d2010-05-31 10:56:17 +02009048 if (curproxy->mon_mask.s_addr)
9049 listener->options |= LI_O_CHK_MONNET;
9050
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009051 /* smart accept mode is automatic in HTTP mode */
9052 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009053 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009054 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9055 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009056 }
9057
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009058 /* Release unused SSL configs */
9059 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01009060 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
9061 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009062 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009063
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009064 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009065 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009066 int count, maxproc = 0;
9067
9068 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009069 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009070 if (count > maxproc)
9071 maxproc = count;
9072 }
9073 /* backends have 0, frontends have 1 or more */
9074 if (maxproc != 1)
9075 Warning("Proxy '%s': in multi-process mode, stats will be"
9076 " limited to process assigned to the current request.\n",
9077 curproxy->id);
9078
Willy Tarreau102df612014-05-07 23:56:38 +02009079 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9080 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9081 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009082 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009083 }
Willy Tarreau102df612014-05-07 23:56:38 +02009084 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9085 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9086 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009087 }
9088 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009089
9090 /* create the task associated with the proxy */
9091 curproxy->task = task_new();
9092 if (curproxy->task) {
9093 curproxy->task->context = curproxy;
9094 curproxy->task->process = manage_proxy;
Willy Tarreau918ff602011-07-25 16:33:49 +02009095 } else {
9096 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9097 curproxy->id);
9098 cfgerr++;
9099 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009100 }
9101
Willy Tarreaufbb78422011-06-05 15:38:35 +02009102 /* automatically compute fullconn if not set. We must not do it in the
9103 * loop above because cross-references are not yet fully resolved.
9104 */
9105 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9106 /* If <fullconn> is not set, let's set it to 10% of the sum of
9107 * the possible incoming frontend's maxconns.
9108 */
9109 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009110 /* we have the sum of the maxconns in <total>. We only
9111 * keep 10% of that sum to set the default fullconn, with
9112 * a hard minimum of 1 (to avoid a divide by zero).
9113 */
Emeric Brun3f783572017-01-12 11:21:28 +01009114 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009115 if (!curproxy->fullconn)
9116 curproxy->fullconn = 1;
9117 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009118 }
9119
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009120 /*
9121 * Recount currently required checks.
9122 */
9123
9124 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9125 int optnum;
9126
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009127 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9128 if (curproxy->options & cfg_opts[optnum].val)
9129 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009130
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009131 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9132 if (curproxy->options2 & cfg_opts2[optnum].val)
9133 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009134 }
9135
Willy Tarreau0fca4832015-05-01 19:12:05 +02009136 /* compute the required process bindings for the peers */
9137 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9138 if (curproxy->table.peers.p)
9139 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9140
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009141 if (cfg_peers) {
9142 struct peers *curpeers = cfg_peers, **last;
Willy Tarreau122541c2011-09-07 21:24:49 +02009143 struct peer *p, *pb;
9144
Willy Tarreau1e273012015-05-01 19:15:17 +02009145 /* Remove all peers sections which don't have a valid listener,
9146 * which are not used by any table, or which are bound to more
9147 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009148 */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02009149 last = &cfg_peers;
Willy Tarreau122541c2011-09-07 21:24:49 +02009150 while (*last) {
9151 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009152
9153 if (curpeers->state == PR_STSTOPPED) {
9154 /* the "disabled" keyword was present */
9155 if (curpeers->peers_fe)
9156 stop_proxy(curpeers->peers_fe);
9157 curpeers->peers_fe = NULL;
9158 }
9159 else if (!curpeers->peers_fe) {
9160 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9161 curpeers->id, localpeer);
9162 }
David Carliere6c39412015-07-02 07:00:17 +00009163 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009164 /* either it's totally stopped or too much used */
9165 if (curpeers->peers_fe->bind_proc) {
9166 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009167 "running in different processes (%d different ones). "
9168 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009169 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009170 cfgerr++;
9171 }
9172 stop_proxy(curpeers->peers_fe);
9173 curpeers->peers_fe = NULL;
9174 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009175 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009176 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009177 last = &curpeers->next;
9178 continue;
9179 }
9180
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009181 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009182 p = curpeers->remote;
9183 while (p) {
9184 pb = p->next;
9185 free(p->id);
9186 free(p);
9187 p = pb;
9188 }
9189
9190 /* Destroy and unlink this curpeers section.
9191 * Note: curpeers is backed up into *last.
9192 */
9193 free(curpeers->id);
9194 curpeers = curpeers->next;
9195 free(*last);
9196 *last = curpeers;
9197 }
9198 }
9199
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009200 /* initialize stick-tables on backend capable proxies. This must not
9201 * be done earlier because the data size may be discovered while parsing
9202 * other proxies.
9203 */
9204 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9205 if (curproxy->state == PR_STSTOPPED)
9206 continue;
9207
9208 if (!stktable_init(&curproxy->table)) {
9209 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9210 cfgerr++;
9211 }
9212 }
9213
Simon Horman0d16a402015-01-30 11:22:58 +09009214 if (mailers) {
9215 struct mailers *curmailers = mailers, **last;
9216 struct mailer *m, *mb;
9217
9218 /* Remove all mailers sections which don't have a valid listener.
9219 * This can happen when a mailers section is never referenced.
9220 */
9221 last = &mailers;
9222 while (*last) {
9223 curmailers = *last;
9224 if (curmailers->users) {
9225 last = &curmailers->next;
9226 continue;
9227 }
9228
9229 Warning("Removing incomplete section 'mailers %s'.\n",
9230 curmailers->id);
9231
9232 m = curmailers->mailer_list;
9233 while (m) {
9234 mb = m->next;
9235 free(m->id);
9236 free(m);
9237 m = mb;
9238 }
9239
9240 /* Destroy and unlink this curmailers section.
9241 * Note: curmailers is backed up into *last.
9242 */
9243 free(curmailers->id);
9244 curmailers = curmailers->next;
9245 free(*last);
9246 *last = curmailers;
9247 }
9248 }
9249
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009250 /* Update server_state_file_name to backend name if backend is supposed to use
9251 * a server-state file locally defined and none has been provided */
9252 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9253 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9254 curproxy->server_state_file_name == NULL)
9255 curproxy->server_state_file_name = strdup(curproxy->id);
9256 }
9257
Willy Tarreau34eb6712011-10-24 18:15:04 +02009258 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009259 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009260 MEM_F_SHARED);
9261
Willy Tarreaubb925012009-07-23 13:36:36 +02009262 if (cfgerr > 0)
9263 err_code |= ERR_ALERT | ERR_FATAL;
9264 out:
9265 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009266}
9267
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009268/*
9269 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9270 * parsing sessions.
9271 */
9272void cfg_register_keywords(struct cfg_kw_list *kwl)
9273{
9274 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9275}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009276
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009277/*
9278 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9279 */
9280void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9281{
9282 LIST_DEL(&kwl->list);
9283 LIST_INIT(&kwl->list);
9284}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009285
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009286/* this function register new section in the haproxy configuration file.
9287 * <section_name> is the name of this new section and <section_parser>
9288 * is the called parser. If two section declaration have the same name,
9289 * only the first declared is used.
9290 */
9291int cfg_register_section(char *section_name,
9292 int (*section_parser)(const char *, int, char **, int))
9293{
9294 struct cfg_section *cs;
9295
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009296 list_for_each_entry(cs, &sections, list) {
9297 if (strcmp(cs->section_name, section_name) == 0) {
9298 Alert("register section '%s': already registered.\n", section_name);
9299 return 0;
9300 }
9301 }
9302
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009303 cs = calloc(1, sizeof(*cs));
9304 if (!cs) {
9305 Alert("register section '%s': out of memory.\n", section_name);
9306 return 0;
9307 }
9308
9309 cs->section_name = section_name;
9310 cs->section_parser = section_parser;
9311
9312 LIST_ADDQ(&sections, &cs->list);
9313
9314 return 1;
9315}
9316
Willy Tarreaubaaee002006-06-26 02:48:02 +02009317/*
David Carlier845efb52015-09-25 11:49:18 +01009318 * free all config section entries
9319 */
9320void cfg_unregister_sections(void)
9321{
9322 struct cfg_section *cs, *ics;
9323
9324 list_for_each_entry_safe(cs, ics, &sections, list) {
9325 LIST_DEL(&cs->list);
9326 free(cs);
9327 }
9328}
9329
Christopher Faulet7110b402016-10-26 11:09:44 +02009330void cfg_backup_sections(struct list *backup_sections)
9331{
9332 struct cfg_section *cs, *ics;
9333
9334 list_for_each_entry_safe(cs, ics, &sections, list) {
9335 LIST_DEL(&cs->list);
9336 LIST_ADDQ(backup_sections, &cs->list);
9337 }
9338}
9339
9340void cfg_restore_sections(struct list *backup_sections)
9341{
9342 struct cfg_section *cs, *ics;
9343
9344 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9345 LIST_DEL(&cs->list);
9346 LIST_ADDQ(&sections, &cs->list);
9347 }
9348}
9349
Willy Tarreau659fbf02016-05-26 17:55:28 +02009350__attribute__((constructor))
9351static void cfgparse_init(void)
9352{
9353 /* Register internal sections */
9354 cfg_register_section("listen", cfg_parse_listen);
9355 cfg_register_section("frontend", cfg_parse_listen);
9356 cfg_register_section("backend", cfg_parse_listen);
9357 cfg_register_section("defaults", cfg_parse_listen);
9358 cfg_register_section("global", cfg_parse_global);
9359 cfg_register_section("userlist", cfg_parse_users);
9360 cfg_register_section("peers", cfg_parse_peers);
9361 cfg_register_section("mailers", cfg_parse_mailers);
9362 cfg_register_section("namespace_list", cfg_parse_netns);
9363 cfg_register_section("resolvers", cfg_parse_resolvers);
9364}
9365
David Carlier845efb52015-09-25 11:49:18 +01009366/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009367 * Local variables:
9368 * c-indent-level: 8
9369 * c-basic-offset: 8
9370 * End:
9371 */