blob: 97adb9f2fd4c1241822517634796440a350b7e78 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010083#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010084#include <proto/task.h>
85#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Emeric Brunfc0421f2012-09-07 17:30:07 +020087#ifdef USE_OPENSSL
88#include <types/ssl_sock.h>
89#include <proto/ssl_sock.h>
90#include <proto/shctx.h>
91#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020092
Willy Tarreauf3c69202006-07-09 16:42:34 +020093/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
94 * ssl-hello-chk option to ensure that the remote server speaks SSL.
95 *
96 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
97 */
98const char sslv3_client_hello_pkt[] = {
99 "\x16" /* ContentType : 0x16 = Hanshake */
100 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
101 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
102 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
103 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
104 "\x03\x00" /* Hello Version : 0x0300 = v3 */
105 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
106 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
107 "\x00" /* Session ID length : empty (no session ID) */
108 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
109 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
110 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
111 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
112 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
113 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
114 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
115 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
116 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
117 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
118 "\x00\x38" "\x00\x39" "\x00\x3A"
119 "\x01" /* Compression Length : 0x01 = 1 byte for types */
120 "\x00" /* Compression Type : 0x00 = NULL compression */
121};
122
Willy Tarreau3842f002009-06-14 11:39:52 +0200123/* various keyword modifiers */
124enum kw_mod {
125 KWM_STD = 0, /* normal */
126 KWM_NO, /* "no" prefixed before the keyword */
127 KWM_DEF, /* "default" prefixed before the keyword */
128};
129
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100130/* permit to store configuration section */
131struct cfg_section {
132 struct list list;
133 char *section_name;
134 int (*section_parser)(const char *, int, char **, int);
135};
136
137/* Used to chain configuration sections definitions. This list
138 * stores struct cfg_section
139 */
140struct list sections = LIST_HEAD_INIT(sections);
141
Willy Tarreau13943ab2006-12-31 00:24:10 +0100142/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100144 const char *name;
145 unsigned int val;
146 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100147 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100149};
150
151/* proxy->options */
152static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100153{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
155 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
156 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
158 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
159 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200161 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200162 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100163 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
165 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
166 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100168#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100170#else
171 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100172#endif
173
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100175};
176
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100177/* proxy->options2 */
178static const struct cfg_opt cfg_opts2[] =
179{
180#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
183 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100184#else
185 { "splice-request", 0, 0, 0, 0 },
186 { "splice-response", 0, 0, 0, 0 },
187 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100188#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100189 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
190 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
191 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
192 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
193 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
194 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
196 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
197 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400198 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100199 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200200 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200201 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100202 { NULL, 0, 0, 0 }
203};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204
Willy Tarreau6daf3432008-01-22 16:44:08 +0100205static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
207int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100208int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100209char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200211/* List head of all known configuration keywords */
212static struct cfg_kw_list cfg_keywords = {
213 .list = LIST_HEAD_INIT(cfg_keywords.list)
214};
215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216/*
217 * converts <str> to a list of listeners which are dynamically allocated.
218 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
219 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
220 * - <port> is a numerical port from 1 to 65535 ;
221 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
222 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
224 * not NULL, it must be a valid pointer to either NULL or a freeable area that
225 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200227int 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 +0200228{
229 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 int port, end;
232
233 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200234
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100237 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
239 str = next;
240 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100241 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 *next++ = 0;
243 }
244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200246 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200247 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100248 if (!ss2)
249 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100251 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100257 if (!port || !end) {
258 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
259 goto fail;
260 }
261
Emeric Bruned760922010-10-22 17:59:25 +0200262 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
266
267 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200268 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200269 goto fail;
270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100272 else if (ss2->ss_family == AF_UNSPEC) {
273 socklen_t addr_len;
274
275 /* We want to attach to an already bound fd whose number
276 * is in the addr part of ss2 when cast to sockaddr_in.
277 * Note that by definition there is a single listener.
278 * We still have to determine the address family to
279 * register the correct protocol.
280 */
281 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
282 addr_len = sizeof(*ss2);
283 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
284 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
285 goto fail;
286 }
287
288 port = end = get_host_port(ss2);
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200292 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100293
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200295 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100296 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200297 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
298 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200299 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300
Willy Tarreau40aa0702013-03-10 23:51:38 +0100301 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200302 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100329 * Report an error in <msg> when there are too many arguments. This version is
330 * intended to be used by keyword parsers so that the message will be included
331 * into the general error message. The index is the current keyword in args.
332 * Return 0 if the number of argument is correct, otherwise build a message and
333 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
334 * message may also be null, it will simply not be produced (useful to check only).
335 * <msg> and <err_code> are only affected on error.
336 */
337int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
338{
339 int i;
340
341 if (!*args[index + maxarg + 1])
342 return 0;
343
344 if (msg) {
345 *msg = NULL;
346 memprintf(msg, "%s", args[0]);
347 for (i = 1; i <= index; i++)
348 memprintf(msg, "%s %s", *msg, args[i]);
349
350 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
351 }
352 if (err_code)
353 *err_code |= ERR_ALERT | ERR_FATAL;
354
355 return 1;
356}
357
358/*
359 * same as too_many_args_idx with a 0 index
360 */
361int too_many_args(int maxarg, char **args, char **msg, int *err_code)
362{
363 return too_many_args_idx(maxarg, 0, args, msg, err_code);
364}
365
366/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200367 * Report a fatal Alert when there is too much arguments
368 * The index is the current keyword in args
369 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
370 * Fill err_code with an ERR_ALERT and an ERR_FATAL
371 */
372int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
373{
374 char *kw = NULL;
375 int i;
376
377 if (!*args[index + maxarg + 1])
378 return 0;
379
380 memprintf(&kw, "%s", args[0]);
381 for (i = 1; i <= index; i++) {
382 memprintf(&kw, "%s %s", kw, args[i]);
383 }
384
385 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
386 free(kw);
387 *err_code |= ERR_ALERT | ERR_FATAL;
388 return 1;
389}
390
391/*
392 * same as alertif_too_many_args_idx with a 0 index
393 */
394int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
395{
396 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
397}
398
Willy Tarreau620408f2016-10-21 16:37:51 +0200399/* Report a warning if a rule is placed after a 'tcp-request session' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
402int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
403{
404 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200412/* Report a warning if a rule is placed after a 'tcp-request content' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau61d18892009-03-31 10:49:21 +0200425/* Report a warning if a rule is placed after a 'block' rule.
426 * Return 1 if the warning has been emitted, otherwise 0.
427 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100428int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200429{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200430 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200431 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
432 file, line, arg);
433 return 1;
434 }
435 return 0;
436}
437
Willy Tarreau5002f572014-04-23 01:32:02 +0200438/* Report a warning if a rule is placed after an 'http_request' rule.
439 * Return 1 if the warning has been emitted, otherwise 0.
440 */
441int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
442{
443 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
444 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
445 file, line, arg);
446 return 1;
447 }
448 return 0;
449}
450
Willy Tarreau61d18892009-03-31 10:49:21 +0200451/* Report a warning if a rule is placed after a reqrewrite rule.
452 * Return 1 if the warning has been emitted, otherwise 0.
453 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100454int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200455{
456 if (proxy->req_exp) {
457 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
458 file, line, arg);
459 return 1;
460 }
461 return 0;
462}
463
464/* Report a warning if a rule is placed after a reqadd rule.
465 * Return 1 if the warning has been emitted, otherwise 0.
466 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100467int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200468{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100469 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200470 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
471 file, line, arg);
472 return 1;
473 }
474 return 0;
475}
476
477/* Report a warning if a rule is placed after a redirect rule.
478 * Return 1 if the warning has been emitted, otherwise 0.
479 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100480int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200481{
482 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
483 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
484 file, line, arg);
485 return 1;
486 }
487 return 0;
488}
489
490/* Report a warning if a rule is placed after a 'use_backend' rule.
491 * Return 1 if the warning has been emitted, otherwise 0.
492 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100493int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200494{
495 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
496 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
497 file, line, arg);
498 return 1;
499 }
500 return 0;
501}
502
Willy Tarreauee445d92014-04-23 01:39:04 +0200503/* Report a warning if a rule is placed after a 'use-server' rule.
504 * Return 1 if the warning has been emitted, otherwise 0.
505 */
506int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
507{
508 if (!LIST_ISEMPTY(&proxy->server_rules)) {
509 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
510 file, line, arg);
511 return 1;
512 }
513 return 0;
514}
515
Willy Tarreaud39ad442016-11-25 15:16:12 +0100516/* report a warning if a redirect rule is dangerously placed */
517int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200518{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100519 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200520 warnif_rule_after_use_server(proxy, file, line, arg);
521}
522
Willy Tarreaud39ad442016-11-25 15:16:12 +0100523/* report a warning if a reqadd rule is dangerously placed */
524int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200525{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100526 return warnif_rule_after_redirect(proxy, file, line, arg) ||
527 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200528}
529
Willy Tarreaud39ad442016-11-25 15:16:12 +0100530/* report a warning if a reqxxx rule is dangerously placed */
531int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200532{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100533 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
534 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200535}
536
537/* report a warning if an http-request rule is dangerously placed */
538int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
539{
Willy Tarreau61d18892009-03-31 10:49:21 +0200540 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100541 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200542}
543
Willy Tarreaud39ad442016-11-25 15:16:12 +0100544/* report a warning if a block rule is dangerously placed */
545int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200546{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100547 return warnif_rule_after_http_req(proxy, file, line, arg) ||
548 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200549}
550
Willy Tarreaud39ad442016-11-25 15:16:12 +0100551/* report a warning if a "tcp request content" rule is dangerously placed */
552int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200553{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100554 return warnif_rule_after_block(proxy, file, line, arg) ||
555 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200556}
557
Willy Tarreaud39ad442016-11-25 15:16:12 +0100558/* report a warning if a "tcp request session" rule is dangerously placed */
559int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200560{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100561 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
562 warnif_misplaced_tcp_cont(proxy, file, line, arg);
563}
564
565/* report a warning if a "tcp request connection" rule is dangerously placed */
566int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
567{
568 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
569 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200570}
571
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100572/* Report it if a request ACL condition uses some keywords that are incompatible
573 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
574 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
575 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100576 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100578{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100579 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200580 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100581
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100583 return 0;
584
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100585 acl = acl_cond_conflicts(cond, where);
586 if (acl) {
587 if (acl->name && *acl->name)
588 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
589 file, line, acl->name, sample_ckp_names(where));
590 else
591 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 +0200592 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100593 return ERR_WARN;
594 }
595 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100596 return 0;
597
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100598 if (acl->name && *acl->name)
599 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200600 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100601 else
602 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200603 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100604 return ERR_WARN;
605}
606
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 * parse a line in a <global> section. Returns the error code, 0 if OK, or
609 * any combination of :
610 * - ERR_ABORT: must abort ASAP
611 * - ERR_FATAL: we can continue parsing but not start the service
612 * - ERR_WARN: a warning has been emitted
613 * - ERR_ALERT: an alert has been emitted
614 * Only the two first ones can stop processing, the two others are just
615 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200617int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618{
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200620 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621
622 if (!strcmp(args[0], "global")) { /* new section */
623 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200624 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200628 if (alertif_too_many_args(0, file, linenum, args, &err_code))
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 global.mode |= MODE_DAEMON;
631 }
632 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DEBUG;
636 }
637 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100640 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200642 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 else if (!strcmp(args[0], "nopoll")) {
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_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100652 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100655 global.tune.options &= ~GTUNE_USE_SPLICE;
656 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200657 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200660 global.tune.options &= ~GTUNE_USE_GAI;
661 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000662 else if (!strcmp(args[0], "noreuseport")) {
663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
665 global.tune.options &= ~GTUNE_USE_REUSEPORT;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 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.recv_enough = atol(args[1]);
721 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100722 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 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.buf_limit = atol(args[1]);
731 if (global.tune.buf_limit) {
732 if (global.tune.buf_limit < 3)
733 global.tune.buf_limit = 3;
734 if (global.tune.buf_limit <= global.tune.reserved_bufs)
735 global.tune.buf_limit = global.tune.reserved_bufs + 1;
736 }
737 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100738 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200739 if (alertif_too_many_args(1, file, linenum, args, &err_code))
740 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.tune.reserved_bufs = atol(args[1]);
747 if (global.tune.reserved_bufs < 2)
748 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100749 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
750 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200752 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
754 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200755 if (*(args[1]) == 0) {
756 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200761 if (global.tune.bufsize <= 0) {
762 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100766 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100767 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200768 }
769 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200770 if (alertif_too_many_args(1, file, linenum, args, &err_code))
771 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
776 }
777 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200778 if (global.tune.maxrewrite < 0) {
779 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200783 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100784 else if (!strcmp(args[0], "tune.idletimer")) {
785 unsigned int idle;
786 const char *res;
787
William Lallemand1a748ae2015-05-19 16:37:23 +0200788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
797 if (res) {
798 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
799 file, linenum, *res, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 if (idle > 65535) {
805 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.idle_timer = idle;
810 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100811 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200812 if (alertif_too_many_args(1, file, linenum, args, &err_code))
813 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100814 if (global.tune.client_rcvbuf != 0) {
815 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT;
817 goto out;
818 }
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.tune.client_rcvbuf = atol(args[1]);
825 }
826 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
828 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100829 if (global.tune.server_rcvbuf != 0) {
830 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT;
832 goto out;
833 }
834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839 global.tune.server_rcvbuf = atol(args[1]);
840 }
841 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
843 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100844 if (global.tune.client_sndbuf != 0) {
845 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT;
847 goto out;
848 }
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 global.tune.client_sndbuf = atol(args[1]);
855 }
856 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
858 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100859 if (global.tune.server_sndbuf != 0) {
860 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT;
862 goto out;
863 }
864 if (*(args[1]) == 0) {
865 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
869 global.tune.server_sndbuf = atol(args[1]);
870 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200871 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200872 if (alertif_too_many_args(1, file, linenum, args, &err_code))
873 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.pipesize = atol(args[1]);
880 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100881 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.cookie_len = atol(args[1]) + 1;
890 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200891 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.max_http_hdr = atol(args[1]);
900 }
William Lallemandf3747832012-11-09 12:33:10 +0100901 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100904 if (*args[1]) {
905 global.tune.comp_maxlevel = atoi(args[1]);
906 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
907 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
908 file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912 } else {
913 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
914 file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200919 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
920 if (*args[1]) {
921 global.tune.pattern_cache = atoi(args[1]);
922 if (global.tune.pattern_cache < 0) {
923 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
924 file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 } else {
929 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
930 file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
933 }
934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200939 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 if (*(args[1]) == 0) {
944 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100948 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
949 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]);
950 err_code |= ERR_WARN;
951 goto out;
952 }
953
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 }
955 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200959 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100968 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
969 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]);
970 err_code |= ERR_WARN;
971 goto out;
972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Simon Horman98637e52014-06-20 12:30:16 +0900974 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200975 if (alertif_too_many_args(0, file, linenum, args, &err_code))
976 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900977 global.external_check = 1;
978 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 /* user/group name handling */
980 else if (!strcmp(args[0], "user")) {
981 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200984 if (global.uid != 0) {
985 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200988 }
989 errno = 0;
990 ha_user = getpwnam(args[1]);
991 if (ha_user != NULL) {
992 global.uid = (int)ha_user->pw_uid;
993 }
994 else {
995 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 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200997 }
998 }
999 else if (!strcmp(args[0], "group")) {
1000 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1002 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001003 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001004 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
1006 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001007 }
1008 errno = 0;
1009 ha_group = getgrnam(args[1]);
1010 if (ha_group != NULL) {
1011 global.gid = (int)ha_group->gr_gid;
1012 }
1013 else {
1014 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 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001016 }
1017 }
1018 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 if (*(args[1]) == 0) {
1023 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 }
1027 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001028 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1029 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1030 file, linenum, args[0], LONGBITS, global.nbproc);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 }
1035 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001036 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 if (global.maxconn != 0) {
1039 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
1048 global.maxconn = atol(args[1]);
1049#ifdef SYSTEM_MAXCONN
1050 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1051 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);
1052 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055#endif /* SYSTEM_MAXCONN */
1056 }
Emeric Brun850efd52014-01-29 12:24:34 +01001057 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001058 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1059 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001060 if (*(args[1]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 if (strcmp(args[1],"none") == 0)
1066 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1067 else if (strcmp(args[1],"required") == 0)
1068 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1069 else {
1070 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001075 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001076 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1077 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001078 if (global.cps_lim != 0) {
1079 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT;
1081 goto out;
1082 }
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088 global.cps_lim = atol(args[1]);
1089 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001090 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001093 if (global.sps_lim != 0) {
1094 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT;
1096 goto out;
1097 }
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
1102 }
1103 global.sps_lim = atol(args[1]);
1104 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001105 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001106 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1107 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001108 if (global.ssl_lim != 0) {
1109 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT;
1111 goto out;
1112 }
1113 if (*(args[1]) == 0) {
1114 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
1118 global.ssl_lim = atol(args[1]);
1119 }
William Lallemandd85f9172012-11-09 17:05:39 +01001120 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1122 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001123 if (*(args[1]) == 0) {
1124 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128 global.comp_rate_lim = atoi(args[1]) * 1024;
1129 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001130 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001133 if (global.maxpipes != 0) {
1134 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001142 }
1143 global.maxpipes = atol(args[1]);
1144 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001145 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001146 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1147 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001148 if (*(args[1]) == 0) {
1149 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
William Lallemande3a7d992012-11-20 11:25:20 +01001153 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001154 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001155 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001156 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1157 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001158 if (*(args[1]) == 0) {
1159 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
1162 }
1163 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001164 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001165 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001169 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001170
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 if (global.rlimit_nofile != 0) {
1175 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 }
1184 global.rlimit_nofile = atol(args[1]);
1185 }
1186 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001187 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (global.chroot != NULL) {
1190 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 global.chroot = strdup(args[1]);
1200 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001201 else if (!strcmp(args[0], "description")) {
1202 int i, len=0;
1203 char *d;
1204
1205 if (!*args[1]) {
1206 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1207 file, linenum, args[0]);
1208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
1210 }
1211
Willy Tarreau348acfe2014-04-14 15:00:39 +02001212 for (i = 1; *args[i]; i++)
1213 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001214
1215 if (global.desc)
1216 free(global.desc);
1217
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001218 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001219
Willy Tarreau348acfe2014-04-14 15:00:39 +02001220 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1221 for (i = 2; *args[i]; i++)
1222 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001223 }
1224 else if (!strcmp(args[0], "node")) {
1225 int i;
1226 char c;
1227
William Lallemand1a748ae2015-05-19 16:37:23 +02001228 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1229 goto out;
1230
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001231 for (i=0; args[1][i]; i++) {
1232 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001233 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1234 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001235 break;
1236 }
1237
1238 if (!i || args[1][i]) {
1239 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1240 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1241 file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245
1246 if (global.node)
1247 free(global.node);
1248
1249 global.node = strdup(args[1]);
1250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001252 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 if (global.pidfile != NULL) {
1255 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 if (*(args[1]) == 0) {
1260 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 }
1264 global.pidfile = strdup(args[1]);
1265 }
Emeric Bruned760922010-10-22 17:59:25 +02001266 else if (!strcmp(args[0], "unix-bind")) {
1267 int cur_arg = 1;
1268 while (*(args[cur_arg])) {
1269 if (!strcmp(args[cur_arg], "prefix")) {
1270 if (global.unix_bind.prefix != NULL) {
1271 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1272 err_code |= ERR_ALERT;
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (*(args[cur_arg+1]) == 0) {
1278 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281 }
1282 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1283 cur_arg += 2;
1284 continue;
1285 }
1286
1287 if (!strcmp(args[cur_arg], "mode")) {
1288
1289 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1290 cur_arg += 2;
1291 continue;
1292 }
1293
1294 if (!strcmp(args[cur_arg], "uid")) {
1295
1296 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1297 cur_arg += 2;
1298 continue;
1299 }
1300
1301 if (!strcmp(args[cur_arg], "gid")) {
1302
1303 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1304 cur_arg += 2;
1305 continue;
1306 }
1307
1308 if (!strcmp(args[cur_arg], "user")) {
1309 struct passwd *user;
1310
1311 user = getpwnam(args[cur_arg + 1]);
1312 if (!user) {
1313 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1314 file, linenum, args[0], args[cur_arg + 1 ]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
1319 global.unix_bind.ux.uid = user->pw_uid;
1320 cur_arg += 2;
1321 continue;
1322 }
1323
1324 if (!strcmp(args[cur_arg], "group")) {
1325 struct group *group;
1326
1327 group = getgrnam(args[cur_arg + 1]);
1328 if (!group) {
1329 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1330 file, linenum, args[0], args[cur_arg + 1 ]);
1331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
1333 }
1334
1335 global.unix_bind.ux.gid = group->gr_gid;
1336 cur_arg += 2;
1337 continue;
1338 }
1339
Willy Tarreaub48f9582011-09-05 01:17:06 +02001340 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001341 file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 }
William Lallemand0f99e342011-10-12 17:50:54 +02001346 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1347 /* delete previous herited or defined syslog servers */
1348 struct logsrv *back;
1349 struct logsrv *tmp;
1350
1351 if (*(args[1]) != 0) {
1352 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356
1357 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1358 LIST_DEL(&tmp->list);
1359 free(tmp);
1360 }
1361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001363 struct sockaddr_storage *sk;
1364 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001365 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001366 int arg = 0;
1367 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001368
William Lallemand1a748ae2015-05-19 16:37:23 +02001369 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1370 goto out;
1371
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 if (*(args[1]) == 0 || *(args[2]) == 0) {
1373 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
William Lallemand0f99e342011-10-12 17:50:54 +02001377
Vincent Bernat02779b62016-04-03 13:48:43 +02001378 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001379
Willy Tarreau18324f52014-06-27 18:10:07 +02001380 /* just after the address, a length may be specified */
1381 if (strcmp(args[arg+2], "len") == 0) {
1382 len = atoi(args[arg+3]);
1383 if (len < 80 || len > 65535) {
1384 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1385 file, linenum, args[arg+3]);
1386 err_code |= ERR_ALERT | ERR_FATAL;
1387 goto out;
1388 }
1389 logsrv->maxlen = len;
1390
1391 /* skip these two args */
1392 arg += 2;
1393 }
1394 else
1395 logsrv->maxlen = MAX_SYSLOG_LEN;
1396
1397 if (logsrv->maxlen > global.max_syslog_len) {
1398 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001399 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1400 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1401 logline = my_realloc2(logline, global.max_syslog_len + 1);
1402 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001403 }
1404
Dragan Dosen1322d092015-09-22 16:05:32 +02001405 /* after the length, a format may be specified */
1406 if (strcmp(args[arg+2], "format") == 0) {
1407 logsrv->format = get_log_format(args[arg+3]);
1408 if (logsrv->format < 0) {
1409 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001411 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001412 goto out;
1413 }
1414
1415 /* skip these two args */
1416 arg += 2;
1417 }
1418
David Carlier97880bb2016-04-08 10:35:26 +01001419 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1420 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001421 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001422 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001423
Willy Tarreau18324f52014-06-27 18:10:07 +02001424 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001425 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001426 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001428 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 }
1430
William Lallemand0f99e342011-10-12 17:50:54 +02001431 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001432 if (*(args[arg+3])) {
1433 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001434 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001435 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001437 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 }
1440
William Lallemand0f99e342011-10-12 17:50:54 +02001441 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001442 if (*(args[arg+4])) {
1443 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001444 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001445 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001447 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001448 }
1449 }
1450
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001451 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001452 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001453 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001454 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 free(logsrv);
1456 goto out;
1457 }
1458 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001459
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001460 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001461 if (port1 != port2) {
1462 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1463 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001464 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001465 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001466 goto out;
1467 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001468
William Lallemand0f99e342011-10-12 17:50:54 +02001469 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001470 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001471 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
William Lallemand0f99e342011-10-12 17:50:54 +02001474 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001475 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001476 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1477 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001478
1479 if (global.log_send_hostname != NULL) {
1480 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1481 err_code |= ERR_ALERT;
1482 goto out;
1483 }
1484
1485 if (*(args[1]))
1486 name = args[1];
1487 else
1488 name = hostname;
1489
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001490 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001491 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001492 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001493 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1494 if (global.server_state_base != NULL) {
1495 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1496 err_code |= ERR_ALERT;
1497 goto out;
1498 }
1499
1500 if (!*(args[1])) {
1501 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1502 err_code |= ERR_FATAL;
1503 goto out;
1504 }
1505
1506 global.server_state_base = strdup(args[1]);
1507 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001508 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1509 if (global.server_state_file != NULL) {
1510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1511 err_code |= ERR_ALERT;
1512 goto out;
1513 }
1514
1515 if (!*(args[1])) {
1516 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1517 err_code |= ERR_FATAL;
1518 goto out;
1519 }
1520
1521 global.server_state_file = strdup(args[1]);
1522 }
Kevinm48936af2010-12-22 16:08:21 +00001523 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001524 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1525 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001526 if (*(args[1]) == 0) {
1527 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001531 chunk_destroy(&global.log_tag);
1532 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001533 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001534 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001535 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1536 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001537 if (global.spread_checks != 0) {
1538 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001539 err_code |= ERR_ALERT;
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 }
1542 if (*(args[1]) == 0) {
1543 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001546 }
1547 global.spread_checks = atol(args[1]);
1548 if (global.spread_checks < 0 || global.spread_checks > 50) {
1549 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001553 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1554 const char *err;
1555 unsigned int val;
1556
William Lallemand1a748ae2015-05-19 16:37:23 +02001557 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1558 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001559 if (*(args[1]) == 0) {
1560 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564
1565 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1566 if (err) {
1567 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 }
1570 global.max_spread_checks = val;
1571 if (global.max_spread_checks < 0) {
1572 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 }
1575 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001576 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1577#ifdef USE_CPU_AFFINITY
1578 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001579 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001580 unsigned long cpus = 0;
1581
1582 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001583 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001584 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001585 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001586 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001587 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001588 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001589 proc = atol(args[1]);
1590 if (proc >= 1 && proc <= LONGBITS)
1591 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 }
1593
1594 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001595 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",
1596 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
1601 cur_arg = 2;
1602 while (*args[cur_arg]) {
1603 unsigned int low, high;
1604
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001605 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 char *dash = strchr(args[cur_arg], '-');
1607
1608 low = high = str2uic(args[cur_arg]);
1609 if (dash)
1610 high = str2uic(dash + 1);
1611
1612 if (high < low) {
1613 unsigned int swap = low;
1614 low = high;
1615 high = swap;
1616 }
1617
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001618 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001619 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001620 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
1625 while (low <= high)
1626 cpus |= 1UL << low++;
1627 }
1628 else {
1629 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1630 file, linenum, args[0], args[cur_arg]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
1634 cur_arg++;
1635 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001636 for (i = 0; i < LONGBITS; i++)
1637 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001638 global.cpu_map[i] = cpus;
1639#else
1640 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
1643#endif
1644 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001645 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1646 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1647 goto out;
1648
1649 if (*(args[2]) == 0) {
1650 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654
1655 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1656 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1657 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
1660 }
1661 }
1662 else if (!strcmp(args[0], "unsetenv")) {
1663 int arg;
1664
1665 if (*(args[1]) == 0) {
1666 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669 }
1670
1671 for (arg = 1; *args[arg]; arg++) {
1672 if (unsetenv(args[arg]) != 0) {
1673 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
1676 }
1677 }
1678 }
1679 else if (!strcmp(args[0], "resetenv")) {
1680 extern char **environ;
1681 char **env = environ;
1682
1683 /* args contain variable names to keep, one per argument */
1684 while (*env) {
1685 int arg;
1686
1687 /* look for current variable in among all those we want to keep */
1688 for (arg = 1; *args[arg]; arg++) {
1689 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1690 (*env)[strlen(args[arg])] == '=')
1691 break;
1692 }
1693
1694 /* delete this variable */
1695 if (!*args[arg]) {
1696 char *delim = strchr(*env, '=');
1697
1698 if (!delim || delim - *env >= trash.size) {
1699 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703
1704 memcpy(trash.str, *env, delim - *env);
1705 trash.str[delim - *env] = 0;
1706
1707 if (unsetenv(trash.str) != 0) {
1708 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712 }
1713 else
1714 env++;
1715 }
1716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001718 struct cfg_kw_list *kwl;
1719 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001720 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001721
1722 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1723 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1724 if (kwl->kw[index].section != CFG_GLOBAL)
1725 continue;
1726 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001727 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001728 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001729 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001731 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001732 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001733 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_WARN;
1735 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001736 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001737 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001738 }
1739 }
1740 }
1741
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001745
Willy Tarreau058e9072009-07-20 09:30:05 +02001746 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001747 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001748 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749}
1750
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001751void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001753 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 defproxy.mode = PR_MODE_TCP;
1755 defproxy.state = PR_STNEW;
1756 defproxy.maxconn = cfg_maxpconn;
1757 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001758 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001759 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001760
Simon Horman66183002013-02-23 10:16:43 +09001761 defproxy.defsrv.check.inter = DEF_CHKINTR;
1762 defproxy.defsrv.check.fastinter = 0;
1763 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001764 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1765 defproxy.defsrv.agent.fastinter = 0;
1766 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001767 defproxy.defsrv.check.rise = DEF_RISETIME;
1768 defproxy.defsrv.check.fall = DEF_FALLTIME;
1769 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1770 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001771 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001772 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001773 defproxy.defsrv.maxqueue = 0;
1774 defproxy.defsrv.minconn = 0;
1775 defproxy.defsrv.maxconn = 0;
1776 defproxy.defsrv.slowstart = 0;
1777 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1778 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1779 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001780
1781 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001782 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783}
1784
Willy Tarreauade5ec42010-01-28 19:33:49 +01001785
Willy Tarreau63af98d2014-05-18 08:11:41 +02001786/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1787 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1788 * ERR_FATAL in case of error.
1789 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001790static int create_cond_regex_rule(const char *file, int line,
1791 struct proxy *px, int dir, int action, int flags,
1792 const char *cmd, const char *reg, const char *repl,
1793 const char **cond_start)
1794{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001795 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001796 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001797 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001798 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001799 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001800 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001801 int cs;
1802 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001803
1804 if (px == &defproxy) {
1805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001806 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001807 goto err;
1808 }
1809
1810 if (*reg == 0) {
1811 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001813 goto err;
1814 }
1815
Christopher Faulet898566e2016-10-26 11:06:28 +02001816 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001817 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001818
Willy Tarreau5321c422010-01-28 20:35:13 +01001819 if (cond_start &&
1820 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001821 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1822 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1823 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001824 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001825 goto err;
1826 }
1827 }
1828 else if (cond_start && **cond_start) {
1829 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1830 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001831 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001832 goto err;
1833 }
1834
Willy Tarreau63af98d2014-05-18 08:11:41 +02001835 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001836 (dir == SMP_OPT_DIR_REQ) ?
1837 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1838 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1839 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001840
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001841 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001842 if (!preg) {
1843 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001844 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001845 goto err;
1846 }
1847
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001848 cs = !(flags & REG_ICASE);
1849 cap = !(flags & REG_NOSUB);
1850 error = NULL;
1851 if (!regex_comp(reg, preg, cs, cap, &error)) {
1852 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1853 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001854 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001855 goto err;
1856 }
1857
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001858 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001859 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 if (repl && err) {
1861 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1862 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_ALERT | ERR_FATAL;
1864 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001865 }
1866
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001867 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 ret_code |= ERR_WARN;
1869
1870 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871
Willy Tarreau63af98d2014-05-18 08:11:41 +02001872 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001873 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874 err:
1875 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001876 free(errmsg);
1877 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878}
1879
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880/*
William Lallemand51097192015-04-14 16:35:22 +02001881 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001882 * Returns the error code, 0 if OK, or any combination of :
1883 * - ERR_ABORT: must abort ASAP
1884 * - ERR_FATAL: we can continue parsing but not start the service
1885 * - ERR_WARN: a warning has been emitted
1886 * - ERR_ALERT: an alert has been emitted
1887 * Only the two first ones can stop processing, the two others are just
1888 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001890int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1891{
1892 static struct peers *curpeers = NULL;
1893 struct peer *newpeer = NULL;
1894 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001895 struct bind_conf *bind_conf;
1896 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001897 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001898 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001899
1900 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001901 if (!*args[1]) {
1902 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001903 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001904 goto out;
1905 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001906
William Lallemand6e62fb62015-04-28 16:55:23 +02001907 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1908 goto out;
1909
Emeric Brun32da3c42010-09-23 18:39:19 +02001910 err = invalid_char(args[1]);
1911 if (err) {
1912 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1913 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001914 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001915 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 }
1917
1918 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1919 /*
1920 * If there are two proxies with the same name only following
1921 * combinations are allowed:
1922 */
1923 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001924 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 +02001925 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001927 }
1928 }
1929
Vincent Bernat02779b62016-04-03 13:48:43 +02001930 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001931 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1932 err_code |= ERR_ALERT | ERR_ABORT;
1933 goto out;
1934 }
1935
1936 curpeers->next = peers;
1937 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001938 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001939 curpeers->conf.line = linenum;
1940 curpeers->last_change = now.tv_sec;
1941 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001942 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001943 }
1944 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001945 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001946 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001947 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001948
1949 if (!*args[2]) {
1950 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1951 file, linenum, args[0]);
1952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
1954 }
1955
1956 err = invalid_char(args[1]);
1957 if (err) {
1958 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1959 file, linenum, *err, args[1]);
1960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
1962 }
1963
Vincent Bernat02779b62016-04-03 13:48:43 +02001964 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1966 err_code |= ERR_ALERT | ERR_ABORT;
1967 goto out;
1968 }
1969
1970 /* the peers are linked backwards first */
1971 curpeers->count++;
1972 newpeer->next = curpeers->remote;
1973 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001974 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001975 newpeer->conf.line = linenum;
1976
1977 newpeer->last_change = now.tv_sec;
1978 newpeer->id = strdup(args[1]);
1979
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001980 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001981 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001982 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001985 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001986
1987 proto = protocol_by_family(sk->ss_family);
1988 if (!proto || !proto->connect) {
1989 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1990 file, linenum, args[0], args[1]);
1991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
1993 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001994
1995 if (port1 != port2) {
1996 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1997 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
2000 }
2001
Willy Tarreau2aa38802013-02-20 19:20:59 +01002002 if (!port1) {
2003 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2004 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
2007 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002010 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002011 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002012 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002013
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 if (strcmp(newpeer->id, localpeer) == 0) {
2015 /* Current is local peer, it define a frontend */
2016 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002017 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002018
2019 if (!curpeers->peers_fe) {
2020 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2021 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2022 err_code |= ERR_ALERT | ERR_ABORT;
2023 goto out;
2024 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002025
Willy Tarreau237250c2011-07-29 01:49:03 +02002026 init_new_proxy(curpeers->peers_fe);
2027 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002029 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2030 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002031 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002032
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002033 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002034
Willy Tarreau902636f2013-03-10 19:44:48 +01002035 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2036 if (errmsg && *errmsg) {
2037 indent_msg(&errmsg, 2);
2038 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002039 }
2040 else
2041 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2042 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 err_code |= ERR_FATAL;
2044 goto out;
2045 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002046
2047 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002048 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002049 l->maxconn = curpeers->peers_fe->maxconn;
2050 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002051 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002052 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002053 l->analysers |= curpeers->peers_fe->fe_req_ana;
2054 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002055 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2056 global.maxsock += l->maxconn;
2057 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002058 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002059 else {
2060 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2061 file, linenum, args[0], args[1],
2062 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2063 err_code |= ERR_FATAL;
2064 goto out;
2065 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002066 }
2067 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002068 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2069 curpeers->state = PR_STSTOPPED;
2070 }
2071 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2072 curpeers->state = PR_STNEW;
2073 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 else if (*args[0] != 0) {
2075 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
2078 }
2079
2080out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002082 return err_code;
2083}
2084
Baptiste Assmann325137d2015-04-13 23:40:55 +02002085/*
2086 * Parse a <resolvers> section.
2087 * Returns the error code, 0 if OK, or any combination of :
2088 * - ERR_ABORT: must abort ASAP
2089 * - ERR_FATAL: we can continue parsing but not start the service
2090 * - ERR_WARN: a warning has been emitted
2091 * - ERR_ALERT: an alert has been emitted
2092 * Only the two first ones can stop processing, the two others are just
2093 * indicators.
2094 */
2095int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2096{
2097 static struct dns_resolvers *curr_resolvers = NULL;
2098 struct dns_nameserver *newnameserver = NULL;
2099 const char *err;
2100 int err_code = 0;
2101 char *errmsg = NULL;
2102
2103 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2104 if (!*args[1]) {
2105 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2106 err_code |= ERR_ALERT | ERR_ABORT;
2107 goto out;
2108 }
2109
2110 err = invalid_char(args[1]);
2111 if (err) {
2112 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2113 file, linenum, *err, args[0], args[1]);
2114 err_code |= ERR_ALERT | ERR_ABORT;
2115 goto out;
2116 }
2117
2118 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2119 /* Error if two resolvers owns the same name */
2120 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2121 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2122 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2123 err_code |= ERR_ALERT | ERR_ABORT;
2124 }
2125 }
2126
Vincent Bernat02779b62016-04-03 13:48:43 +02002127 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2129 err_code |= ERR_ALERT | ERR_ABORT;
2130 goto out;
2131 }
2132
2133 /* default values */
2134 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2135 curr_resolvers->conf.file = strdup(file);
2136 curr_resolvers->conf.line = linenum;
2137 curr_resolvers->id = strdup(args[1]);
2138 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002139 /* default hold period for nx, other, refuse and timeout is 30s */
2140 curr_resolvers->hold.nx = 30000;
2141 curr_resolvers->hold.other = 30000;
2142 curr_resolvers->hold.refused = 30000;
2143 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002144 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002145 curr_resolvers->hold.valid = 10000;
2146 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002147 curr_resolvers->resolve_retries = 3;
2148 LIST_INIT(&curr_resolvers->nameserver_list);
2149 LIST_INIT(&curr_resolvers->curr_resolution);
2150 }
2151 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2152 struct sockaddr_storage *sk;
2153 int port1, port2;
2154 struct protocol *proto;
2155
2156 if (!*args[2]) {
2157 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2158 file, linenum, args[0]);
2159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
2161 }
2162
2163 err = invalid_char(args[1]);
2164 if (err) {
2165 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2166 file, linenum, *err, args[1]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
Baptiste Assmanna315c552015-11-02 22:55:49 +01002171 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2172 /* Error if two resolvers owns the same name */
2173 if (strcmp(newnameserver->id, args[1]) == 0) {
2174 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2175 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 }
2178 }
2179
Vincent Bernat02779b62016-04-03 13:48:43 +02002180 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002181 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2182 err_code |= ERR_ALERT | ERR_ABORT;
2183 goto out;
2184 }
2185
2186 /* the nameservers are linked backward first */
2187 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2188 curr_resolvers->count_nameservers++;
2189 newnameserver->resolvers = curr_resolvers;
2190 newnameserver->conf.file = strdup(file);
2191 newnameserver->conf.line = linenum;
2192 newnameserver->id = strdup(args[1]);
2193
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002194 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002195 if (!sk) {
2196 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
2201 proto = protocol_by_family(sk->ss_family);
2202 if (!proto || !proto->connect) {
2203 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2204 file, linenum, args[0], args[1]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209 if (port1 != port2) {
2210 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2211 file, linenum, args[0], args[1], args[2]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002216 if (!port1 && !port2) {
2217 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2218 file, linenum, args[0], args[1]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
2222
Baptiste Assmann325137d2015-04-13 23:40:55 +02002223 newnameserver->addr = *sk;
2224 }
2225 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2226 const char *res;
2227 unsigned int time;
2228
2229 if (!*args[2]) {
2230 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2231 file, linenum, args[0]);
2232 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2237 if (res) {
2238 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2239 file, linenum, *res, args[0]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002243 if (strcmp(args[1], "nx") == 0)
2244 curr_resolvers->hold.nx = time;
2245 else if (strcmp(args[1], "other") == 0)
2246 curr_resolvers->hold.other = time;
2247 else if (strcmp(args[1], "refused") == 0)
2248 curr_resolvers->hold.refused = time;
2249 else if (strcmp(args[1], "timeout") == 0)
2250 curr_resolvers->hold.timeout = time;
2251 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002252 curr_resolvers->hold.valid = time;
2253 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002254 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2255 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
2258 }
2259
2260 }
2261 else if (strcmp(args[0], "resolve_retries") == 0) {
2262 if (!*args[1]) {
2263 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2264 file, linenum, args[0]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268 curr_resolvers->resolve_retries = atoi(args[1]);
2269 }
2270 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002271 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002272 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2273 file, linenum, args[0]);
2274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
2276 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002277 else if (strcmp(args[1], "retry") == 0) {
2278 const char *res;
2279 unsigned int timeout_retry;
2280
2281 if (!*args[2]) {
2282 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2283 file, linenum, args[0], args[1]);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2288 if (res) {
2289 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2290 file, linenum, *res, args[0], args[1]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294 curr_resolvers->timeout.retry = timeout_retry;
2295 }
2296 else {
2297 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2298 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002302 } /* neither "nameserver" nor "resolvers" */
2303 else if (*args[0] != 0) {
2304 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309 out:
2310 free(errmsg);
2311 return err_code;
2312}
Simon Horman0d16a402015-01-30 11:22:58 +09002313
2314/*
William Lallemand51097192015-04-14 16:35:22 +02002315 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002316 * Returns the error code, 0 if OK, or any combination of :
2317 * - ERR_ABORT: must abort ASAP
2318 * - ERR_FATAL: we can continue parsing but not start the service
2319 * - ERR_WARN: a warning has been emitted
2320 * - ERR_ALERT: an alert has been emitted
2321 * Only the two first ones can stop processing, the two others are just
2322 * indicators.
2323 */
2324int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2325{
2326 static struct mailers *curmailers = NULL;
2327 struct mailer *newmailer = NULL;
2328 const char *err;
2329 int err_code = 0;
2330 char *errmsg = NULL;
2331
2332 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2333 if (!*args[1]) {
2334 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2335 err_code |= ERR_ALERT | ERR_ABORT;
2336 goto out;
2337 }
2338
2339 err = invalid_char(args[1]);
2340 if (err) {
2341 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2342 file, linenum, *err, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_ABORT;
2344 goto out;
2345 }
2346
2347 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2348 /*
2349 * If there are two proxies with the same name only following
2350 * combinations are allowed:
2351 */
2352 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002353 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 +09002354 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002356 }
2357 }
2358
Vincent Bernat02779b62016-04-03 13:48:43 +02002359 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2361 err_code |= ERR_ALERT | ERR_ABORT;
2362 goto out;
2363 }
2364
2365 curmailers->next = mailers;
2366 mailers = curmailers;
2367 curmailers->conf.file = strdup(file);
2368 curmailers->conf.line = linenum;
2369 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002370 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2371 * But need enough time so that timeouts don't occur
2372 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002373 }
2374 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2375 struct sockaddr_storage *sk;
2376 int port1, port2;
2377 struct protocol *proto;
2378
2379 if (!*args[2]) {
2380 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2381 file, linenum, args[0]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385
2386 err = invalid_char(args[1]);
2387 if (err) {
2388 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2389 file, linenum, *err, args[1]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Vincent Bernat02779b62016-04-03 13:48:43 +02002394 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2396 err_code |= ERR_ALERT | ERR_ABORT;
2397 goto out;
2398 }
2399
2400 /* the mailers are linked backwards first */
2401 curmailers->count++;
2402 newmailer->next = curmailers->mailer_list;
2403 curmailers->mailer_list = newmailer;
2404 newmailer->mailers = curmailers;
2405 newmailer->conf.file = strdup(file);
2406 newmailer->conf.line = linenum;
2407
2408 newmailer->id = strdup(args[1]);
2409
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002410 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002411 if (!sk) {
2412 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
2415 }
2416
2417 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002418 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2419 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002420 file, linenum, args[0], args[1]);
2421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
2423 }
2424
2425 if (port1 != port2) {
2426 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2427 file, linenum, args[0], args[1], args[2]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431
2432 if (!port1) {
2433 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2434 file, linenum, args[0], args[1], args[2]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
2439 newmailer->addr = *sk;
2440 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002441 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002442 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002443 }
2444 else if (strcmp(args[0], "timeout") == 0) {
2445 if (!*args[1]) {
2446 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2447 file, linenum, args[0]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451 else if (strcmp(args[1], "mail") == 0) {
2452 const char *res;
2453 unsigned int timeout_mail;
2454 if (!*args[2]) {
2455 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2456 file, linenum, args[0], args[1]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2461 if (res) {
2462 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2463 file, linenum, *res, args[0]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467 if (timeout_mail <= 0) {
2468 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472 curmailers->timeout.mail = timeout_mail;
2473 } else {
2474 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2475 file, linenum, args[0], args[1]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479 }
Simon Horman0d16a402015-01-30 11:22:58 +09002480 else if (*args[0] != 0) {
2481 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486out:
2487 free(errmsg);
2488 return err_code;
2489}
2490
Simon Horman9dc49962015-01-30 11:22:59 +09002491static void free_email_alert(struct proxy *p)
2492{
2493 free(p->email_alert.mailers.name);
2494 p->email_alert.mailers.name = NULL;
2495 free(p->email_alert.from);
2496 p->email_alert.from = NULL;
2497 free(p->email_alert.to);
2498 p->email_alert.to = NULL;
2499 free(p->email_alert.myhostname);
2500 p->email_alert.myhostname = NULL;
2501}
2502
Willy Tarreau3842f002009-06-14 11:39:52 +02002503int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504{
2505 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002506 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002507 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002508 int rc;
2509 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002510 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002511 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002512 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002513 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002514 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515
Willy Tarreau977b8e42006-12-29 14:19:17 +01002516 if (!strcmp(args[0], "listen"))
2517 rc = PR_CAP_LISTEN;
2518 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002519 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002520 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002521 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522 else
2523 rc = PR_CAP_NONE;
2524
2525 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (!*args[1]) {
2527 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002528 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002533
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 err = invalid_char(args[1]);
2535 if (err) {
2536 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2537 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002539 }
2540
Willy Tarreau8f50b682015-05-26 11:45:02 +02002541 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2542 if (curproxy) {
2543 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2544 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2545 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002547 }
2548
Vincent Bernat02779b62016-04-03 13:48:43 +02002549 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_ABORT;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002554
Willy Tarreau97cb7802010-01-03 20:23:58 +01002555 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->next = proxy;
2557 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002558 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2559 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002560 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002563 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564
William Lallemand6e62fb62015-04-28 16:55:23 +02002565 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2566 if (curproxy->cap & PR_CAP_FE)
2567 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002572 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002573 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002577 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002578 curproxy->no_options = defproxy.no_options;
2579 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002580 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002581 curproxy->except_net = defproxy.except_net;
2582 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002583 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002584 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002586 if (defproxy.fwdfor_hdr_len) {
2587 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2588 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2589 }
2590
Willy Tarreaub86db342009-11-30 11:50:16 +01002591 if (defproxy.orgto_hdr_len) {
2592 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2593 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2594 }
2595
Mark Lamourinec2247f02012-01-04 13:02:01 -05002596 if (defproxy.server_id_hdr_len) {
2597 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2598 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2599 }
2600
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (curproxy->cap & PR_CAP_FE) {
2602 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002603 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002604 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605
2606 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2608 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
2610 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002614 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002615 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616 curproxy->fullconn = defproxy.fullconn;
2617 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002618 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002619 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002621 if (defproxy.check_req) {
2622 curproxy->check_req = calloc(1, defproxy.check_len);
2623 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2624 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002625 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002627 if (defproxy.expect_str) {
2628 curproxy->expect_str = strdup(defproxy.expect_str);
2629 if (defproxy.expect_regex) {
2630 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002631 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2632 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002633 }
2634 }
2635
Willy Tarreau67402132012-05-31 20:40:20 +02002636 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002637 if (defproxy.cookie_name)
2638 curproxy->cookie_name = strdup(defproxy.cookie_name);
2639 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002640 if (defproxy.cookie_domain)
2641 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002642
Willy Tarreau31936852010-10-06 16:59:56 +02002643 if (defproxy.cookie_maxidle)
2644 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2645
2646 if (defproxy.cookie_maxlife)
2647 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2648
Emeric Brun647caf12009-06-30 17:57:00 +02002649 if (defproxy.rdp_cookie_name)
2650 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2651 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2652
Willy Tarreau01732802007-11-01 22:48:15 +01002653 if (defproxy.url_param_name)
2654 curproxy->url_param_name = strdup(defproxy.url_param_name);
2655 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002656
Benoitaffb4812009-03-25 13:02:10 +01002657 if (defproxy.hh_name)
2658 curproxy->hh_name = strdup(defproxy.hh_name);
2659 curproxy->hh_len = defproxy.hh_len;
2660 curproxy->hh_match_domain = defproxy.hh_match_domain;
2661
Willy Tarreauef9a3602012-12-08 22:29:20 +01002662 if (defproxy.conn_src.iface_name)
2663 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2664 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002665 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002666#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002667 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002668#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002669 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002671
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002672 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002673 if (defproxy.capture_name)
2674 curproxy->capture_name = strdup(defproxy.capture_name);
2675 curproxy->capture_namelen = defproxy.capture_namelen;
2676 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002680 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002681 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002682 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002683 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002684 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002685 curproxy->mon_net = defproxy.mon_net;
2686 curproxy->mon_mask = defproxy.mon_mask;
2687 if (defproxy.monitor_uri)
2688 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2689 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002690 if (defproxy.defbe.name)
2691 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002692
2693 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002694 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2695 if (curproxy->conf.logformat_string &&
2696 curproxy->conf.logformat_string != default_http_log_format &&
2697 curproxy->conf.logformat_string != default_tcp_log_format &&
2698 curproxy->conf.logformat_string != clf_http_log_format)
2699 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2700
2701 if (defproxy.conf.lfs_file) {
2702 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2703 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2704 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002705
2706 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2707 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2708 if (curproxy->conf.logformat_sd_string &&
2709 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2710 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2711
2712 if (defproxy.conf.lfsd_file) {
2713 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2714 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2715 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002716 }
2717
2718 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002719 curproxy->timeout.connect = defproxy.timeout.connect;
2720 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002721 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002722 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002723 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002724 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002725 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002726 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002727 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002728 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 }
2730
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002732 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002733
2734 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002735 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002736 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002737 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002738 LIST_INIT(&node->list);
2739 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2740 }
2741
Willy Tarreau62a61232013-04-12 18:13:46 +02002742 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2743 if (curproxy->conf.uniqueid_format_string)
2744 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2745
Dragan Dosen43885c72015-10-01 13:18:13 +02002746 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002747
Willy Tarreau62a61232013-04-12 18:13:46 +02002748 if (defproxy.conf.uif_file) {
2749 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2750 curproxy->conf.uif_line = defproxy.conf.uif_line;
2751 }
William Lallemanda73203e2012-03-12 12:48:57 +01002752
2753 /* copy default header unique id */
2754 if (defproxy.header_unique_id)
2755 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2756
William Lallemand82fe75c2012-10-23 10:25:10 +02002757 /* default compression options */
2758 if (defproxy.comp != NULL) {
2759 curproxy->comp = calloc(1, sizeof(struct comp));
2760 curproxy->comp->algos = defproxy.comp->algos;
2761 curproxy->comp->types = defproxy.comp->types;
2762 }
2763
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002765 curproxy->conf.used_listener_id = EB_ROOT;
2766 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002767
Simon Horman98637e52014-06-20 12:30:16 +09002768 if (defproxy.check_path)
2769 curproxy->check_path = strdup(defproxy.check_path);
2770 if (defproxy.check_command)
2771 curproxy->check_command = strdup(defproxy.check_command);
2772
Simon Horman9dc49962015-01-30 11:22:59 +09002773 if (defproxy.email_alert.mailers.name)
2774 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2775 if (defproxy.email_alert.from)
2776 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2777 if (defproxy.email_alert.to)
2778 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2779 if (defproxy.email_alert.myhostname)
2780 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002781 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002782 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002783
Willy Tarreau93893792009-07-23 13:19:11 +02002784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 }
2786 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2787 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002788 /* FIXME-20070101: we should do this too at the end of the
2789 * config parsing to free all default values.
2790 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002791 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2792 err_code |= ERR_ABORT;
2793 goto out;
2794 }
2795
Willy Tarreaua534fea2008-08-03 12:19:50 +02002796 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002797 free(defproxy.check_command);
2798 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002799 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002800 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002801 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002802 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002803 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002804 free(defproxy.capture_name);
2805 free(defproxy.monitor_uri);
2806 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002807 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002808 free(defproxy.fwdfor_hdr_name);
2809 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002810 free(defproxy.orgto_hdr_name);
2811 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002812 free(defproxy.server_id_hdr_name);
2813 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002814 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002815 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002816 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002817 free(defproxy.expect_regex);
2818 defproxy.expect_regex = NULL;
2819 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002820
Willy Tarreau62a61232013-04-12 18:13:46 +02002821 if (defproxy.conf.logformat_string != default_http_log_format &&
2822 defproxy.conf.logformat_string != default_tcp_log_format &&
2823 defproxy.conf.logformat_string != clf_http_log_format)
2824 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002825
Willy Tarreau62a61232013-04-12 18:13:46 +02002826 free(defproxy.conf.uniqueid_format_string);
2827 free(defproxy.conf.lfs_file);
2828 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002829 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002830 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002831
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002832 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2833 free(defproxy.conf.logformat_sd_string);
2834 free(defproxy.conf.lfsd_file);
2835
Willy Tarreaua534fea2008-08-03 12:19:50 +02002836 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002837 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002838
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 /* we cannot free uri_auth because it might already be used */
2840 init_default_instance();
2841 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002842 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2843 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002844 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
2847 else if (curproxy == NULL) {
2848 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002852
2853 /* update the current file and line being parsed */
2854 curproxy->conf.args.file = curproxy->conf.file;
2855 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856
2857 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002858 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2859 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2860 if (err_code & ERR_FATAL)
2861 goto out;
2862 }
2863 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002864 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002865 int cur_arg;
2866
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 if (curproxy == &defproxy) {
2868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002872 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874
Willy Tarreau24709282013-03-10 21:32:12 +01002875 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002876 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002881
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002882 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002883
2884 /* use default settings for unix sockets */
2885 bind_conf->ux.uid = global.unix_bind.ux.uid;
2886 bind_conf->ux.gid = global.unix_bind.ux.gid;
2887 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002888
2889 /* NOTE: the following line might create several listeners if there
2890 * are comma-separated IPs or port ranges. So all further processing
2891 * will have to be applied to all listeners created after last_listen.
2892 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002893 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2894 if (errmsg && *errmsg) {
2895 indent_msg(&errmsg, 2);
2896 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002897 }
2898 else
2899 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2900 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002904
Willy Tarreau4348fad2012-09-20 16:48:07 +02002905 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2906 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002907 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002908 }
2909
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002910 cur_arg = 2;
2911 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002912 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002913 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002914 char *err;
2915
Willy Tarreau26982662012-09-12 23:17:10 +02002916 kw = bind_find_kw(args[cur_arg]);
2917 if (kw) {
2918 char *err = NULL;
2919 int code;
2920
2921 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002922 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2923 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002924 cur_arg += 1 + kw->skip ;
2925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
2927 }
2928
Willy Tarreau4348fad2012-09-20 16:48:07 +02002929 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002930 err_code |= code;
2931
2932 if (code) {
2933 if (err && *err) {
2934 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002935 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002936 }
2937 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002938 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2939 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002940 if (code & ERR_FATAL) {
2941 free(err);
2942 cur_arg += 1 + kw->skip;
2943 goto out;
2944 }
2945 }
2946 free(err);
2947 cur_arg += 1 + kw->skip;
2948 continue;
2949 }
2950
Willy Tarreau8638f482012-09-18 18:01:17 +02002951 err = NULL;
2952 if (!bind_dumped) {
2953 bind_dump_kws(&err);
2954 indent_msg(&err, 4);
2955 bind_dumped = 1;
2956 }
2957
2958 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2959 file, linenum, args[0], args[1], args[cur_arg],
2960 err ? " Registered keywords :" : "", err ? err : "");
2961 free(err);
2962
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002965 }
Willy Tarreau93893792009-07-23 13:19:11 +02002966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
2968 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002969 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2971 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002975 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002977
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 /* flush useless bits */
2979 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002982 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002983 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002985
William Lallemanddf1425a2015-04-28 20:17:49 +02002986 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2987 goto out;
2988
Willy Tarreau1c47f852006-07-09 08:22:27 +02002989 if (!*args[1]) {
2990 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002994 }
2995
Willy Tarreaua534fea2008-08-03 12:19:50 +02002996 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002997 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002998 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002999 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003000 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3001
Willy Tarreau93893792009-07-23 13:19:11 +02003002 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003005 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3006 goto out;
3007
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3009 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3010 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3011 else {
3012 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
3016 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003017 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003018 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003019
3020 if (curproxy == &defproxy) {
3021 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003025 }
3026
William Lallemanddf1425a2015-04-28 20:17:49 +02003027 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3028 goto out;
3029
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003030 if (!*args[1]) {
3031 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3032 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003035 }
3036
3037 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003038 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003039 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003040
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003041 if (curproxy->uuid <= 0) {
3042 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003043 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003046 }
3047
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003048 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3049 if (node) {
3050 struct proxy *target = container_of(node, struct proxy, conf.id);
3051 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3052 file, linenum, proxy_type_str(curproxy), curproxy->id,
3053 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003058 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003059 else if (!strcmp(args[0], "description")) {
3060 int i, len=0;
3061 char *d;
3062
Cyril Bonté99ed3272010-01-24 23:29:44 +01003063 if (curproxy == &defproxy) {
3064 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3065 file, linenum, args[0]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
3069
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003070 if (!*args[1]) {
3071 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3072 file, linenum, args[0]);
3073 return -1;
3074 }
3075
Willy Tarreau348acfe2014-04-14 15:00:39 +02003076 for (i = 1; *args[i]; i++)
3077 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003078
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003079 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003080 curproxy->desc = d;
3081
Willy Tarreau348acfe2014-04-14 15:00:39 +02003082 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3083 for (i = 2; *args[i]; i++)
3084 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003085
3086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003088 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 curproxy->state = PR_STSTOPPED;
3091 }
3092 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003093 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 curproxy->state = PR_STNEW;
3096 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003097 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3098 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003099 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003100
3101 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003102 unsigned int low, high;
3103
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003104 if (strcmp(args[cur_arg], "all") == 0) {
3105 set = 0;
3106 break;
3107 }
3108 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003109 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003110 }
3111 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003112 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003113 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003114 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003115 char *dash = strchr(args[cur_arg], '-');
3116
3117 low = high = str2uic(args[cur_arg]);
3118 if (dash)
3119 high = str2uic(dash + 1);
3120
3121 if (high < low) {
3122 unsigned int swap = low;
3123 low = high;
3124 high = swap;
3125 }
3126
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003127 if (low < 1 || high > LONGBITS) {
3128 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3129 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003132 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003133 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003134 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003135 }
3136 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003137 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3138 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003141 }
3142 cur_arg++;
3143 }
3144 curproxy->bind_proc = set;
3145 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003146 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003147 if (curproxy == &defproxy) {
3148 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003151 }
3152
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003153 err = invalid_char(args[1]);
3154 if (err) {
3155 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3156 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003158 }
3159
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003160 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003161 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3162 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003165 }
3166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3168 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169
Willy Tarreau977b8e42006-12-29 14:19:17 +01003170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003172
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 if (*(args[1]) == 0) {
3174 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3175 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003179
Willy Tarreau67402132012-05-31 20:40:20 +02003180 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003181 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003182 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003183 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 curproxy->cookie_name = strdup(args[1]);
3185 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003186
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 cur_arg = 2;
3188 while (*(args[cur_arg])) {
3189 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003190 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
3192 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003193 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
3195 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003196 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 }
3198 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003199 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
3201 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003202 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003204 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003205 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003208 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003210 else if (!strcmp(args[cur_arg], "httponly")) {
3211 curproxy->ck_opts |= PR_CK_HTTPONLY;
3212 }
3213 else if (!strcmp(args[cur_arg], "secure")) {
3214 curproxy->ck_opts |= PR_CK_SECURE;
3215 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003216 else if (!strcmp(args[cur_arg], "domain")) {
3217 if (!*args[cur_arg + 1]) {
3218 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3219 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003222 }
3223
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003224 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003225 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003226 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3227 " dots nor does not start with a dot."
3228 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003229 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003230 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003231 }
3232
3233 err = invalid_domainchar(args[cur_arg + 1]);
3234 if (err) {
3235 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3236 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003239 }
3240
Willy Tarreau68a897b2009-12-03 23:28:34 +01003241 if (!curproxy->cookie_domain) {
3242 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3243 } else {
3244 /* one domain was already specified, add another one by
3245 * building the string which will be returned along with
3246 * the cookie.
3247 */
3248 char *new_ptr;
3249 int new_len = strlen(curproxy->cookie_domain) +
3250 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3251 new_ptr = malloc(new_len);
3252 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3253 free(curproxy->cookie_domain);
3254 curproxy->cookie_domain = new_ptr;
3255 }
Willy Tarreau31936852010-10-06 16:59:56 +02003256 cur_arg++;
3257 }
3258 else if (!strcmp(args[cur_arg], "maxidle")) {
3259 unsigned int maxidle;
3260 const char *res;
3261
3262 if (!*args[cur_arg + 1]) {
3263 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3264 file, linenum, args[cur_arg]);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267 }
3268
3269 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3270 if (res) {
3271 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3272 file, linenum, *res, args[cur_arg]);
3273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
3275 }
3276 curproxy->cookie_maxidle = maxidle;
3277 cur_arg++;
3278 }
3279 else if (!strcmp(args[cur_arg], "maxlife")) {
3280 unsigned int maxlife;
3281 const char *res;
3282
3283 if (!*args[cur_arg + 1]) {
3284 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3285 file, linenum, args[cur_arg]);
3286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
3288 }
3289
3290 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3291 if (res) {
3292 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3293 file, linenum, *res, args[cur_arg]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003298 cur_arg++;
3299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003301 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306 cur_arg++;
3307 }
Willy Tarreau67402132012-05-31 20:40:20 +02003308 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3310 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
3313
Willy Tarreau67402132012-05-31 20:40:20 +02003314 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3316 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003319
Willy Tarreau67402132012-05-31 20:40:20 +02003320 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003321 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3322 file, linenum);
3323 err_code |= ERR_ALERT | ERR_FATAL;
3324 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003326 else if (!strcmp(args[0], "email-alert")) {
3327 if (*(args[1]) == 0) {
3328 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3329 file, linenum, args[0]);
3330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
3332 }
3333
3334 if (!strcmp(args[1], "from")) {
3335 if (*(args[1]) == 0) {
3336 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3337 file, linenum, args[1]);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
3341 free(curproxy->email_alert.from);
3342 curproxy->email_alert.from = strdup(args[2]);
3343 }
3344 else if (!strcmp(args[1], "mailers")) {
3345 if (*(args[1]) == 0) {
3346 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3347 file, linenum, args[1]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351 free(curproxy->email_alert.mailers.name);
3352 curproxy->email_alert.mailers.name = strdup(args[2]);
3353 }
3354 else if (!strcmp(args[1], "myhostname")) {
3355 if (*(args[1]) == 0) {
3356 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3357 file, linenum, args[1]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361 free(curproxy->email_alert.myhostname);
3362 curproxy->email_alert.myhostname = strdup(args[2]);
3363 }
Simon Horman64e34162015-02-06 11:11:57 +09003364 else if (!strcmp(args[1], "level")) {
3365 curproxy->email_alert.level = get_log_level(args[2]);
3366 if (curproxy->email_alert.level < 0) {
3367 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3368 file, linenum, args[1], args[2]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372 }
Simon Horman9dc49962015-01-30 11:22:59 +09003373 else if (!strcmp(args[1], "to")) {
3374 if (*(args[1]) == 0) {
3375 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3376 file, linenum, args[1]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380 free(curproxy->email_alert.to);
3381 curproxy->email_alert.to = strdup(args[2]);
3382 }
3383 else {
3384 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3385 file, linenum, args[1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
Simon Horman64e34162015-02-06 11:11:57 +09003389 /* Indicate that the email_alert is at least partially configured */
3390 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003391 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003392 else if (!strcmp(args[0], "external-check")) {
3393 if (*(args[1]) == 0) {
3394 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3395 file, linenum, args[0]);
3396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
3398 }
3399
3400 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003401 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003402 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003403 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003404 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3405 file, linenum, args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409 free(curproxy->check_command);
3410 curproxy->check_command = strdup(args[2]);
3411 }
3412 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003413 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003414 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003415 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003416 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3417 file, linenum, args[1]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421 free(curproxy->check_path);
3422 curproxy->check_path = strdup(args[2]);
3423 }
3424 else {
3425 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3426 file, linenum, args[1]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003431 else if (!strcmp(args[0], "persist")) { /* persist */
3432 if (*(args[1]) == 0) {
3433 Alert("parsing [%s:%d] : missing persist method.\n",
3434 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003437 }
3438
3439 if (!strncmp(args[1], "rdp-cookie", 10)) {
3440 curproxy->options2 |= PR_O2_RDPC_PRST;
3441
Emeric Brunb982a3d2010-01-04 15:45:53 +01003442 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003443 const char *beg, *end;
3444
3445 beg = args[1] + 11;
3446 end = strchr(beg, ')');
3447
William Lallemanddf1425a2015-04-28 20:17:49 +02003448 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3449 goto out;
3450
Emeric Brun647caf12009-06-30 17:57:00 +02003451 if (!end || end == beg) {
3452 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003456 }
3457
3458 free(curproxy->rdp_cookie_name);
3459 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3460 curproxy->rdp_cookie_len = end-beg;
3461 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003462 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003463 free(curproxy->rdp_cookie_name);
3464 curproxy->rdp_cookie_name = strdup("msts");
3465 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3466 }
3467 else { /* syntax */
3468 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3469 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003472 }
3473 }
3474 else {
3475 Alert("parsing [%s:%d] : unknown persist method.\n",
3476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003479 }
3480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003482 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003486 else if (!strcmp(args[0], "load-server-state-from-file")) {
3487 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3488 err_code |= ERR_WARN;
3489 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3490 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3491 }
3492 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3493 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3494 }
3495 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3496 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3497 }
3498 else {
3499 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3500 file, linenum, args[0], args[1]);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
3504 }
3505 else if (!strcmp(args[0], "server-state-file-name")) {
3506 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3507 err_code |= ERR_WARN;
3508 if (*(args[1]) == 0) {
3509 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3510 file, linenum, args[0]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 else if (!strcmp(args[1], "use-backend-name"))
3515 curproxy->server_state_file_name = strdup(curproxy->id);
3516 else
3517 curproxy->server_state_file_name = strdup(args[1]);
3518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003520 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003522
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003524 if (curproxy == &defproxy) {
3525 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529
William Lallemand1a748ae2015-05-19 16:37:23 +02003530 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3531 goto out;
3532
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 if (*(args[4]) == 0) {
3534 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3535 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003539 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 curproxy->capture_name = strdup(args[2]);
3541 curproxy->capture_namelen = strlen(curproxy->capture_name);
3542 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 curproxy->to_log |= LW_COOKIE;
3544 }
3545 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3546 struct cap_hdr *hdr;
3547
3548 if (curproxy == &defproxy) {
3549 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 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
3553
William Lallemand1a748ae2015-05-19 16:37:23 +02003554 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3555 goto out;
3556
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3558 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3559 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 }
3563
Vincent Bernat02779b62016-04-03 13:48:43 +02003564 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 hdr->next = curproxy->req_cap;
3566 hdr->name = strdup(args[3]);
3567 hdr->namelen = strlen(args[3]);
3568 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003569 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 hdr->index = curproxy->nb_req_cap++;
3571 curproxy->req_cap = hdr;
3572 curproxy->to_log |= LW_REQHDR;
3573 }
3574 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3575 struct cap_hdr *hdr;
3576
3577 if (curproxy == &defproxy) {
3578 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 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 }
3582
William Lallemand1a748ae2015-05-19 16:37:23 +02003583 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3584 goto out;
3585
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3587 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3588 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003592 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 hdr->next = curproxy->rsp_cap;
3594 hdr->name = strdup(args[3]);
3595 hdr->namelen = strlen(args[3]);
3596 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003597 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 hdr->index = curproxy->nb_rsp_cap++;
3599 curproxy->rsp_cap = hdr;
3600 curproxy->to_log |= LW_RSPHDR;
3601 }
3602 else {
3603 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
3608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003612
William Lallemanddf1425a2015-04-28 20:17:49 +02003613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3614 goto out;
3615
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 if (*(args[1]) == 0) {
3617 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3618 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 }
3622 curproxy->conn_retries = atol(args[1]);
3623 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003624 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003625 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003626
3627 if (curproxy == &defproxy) {
3628 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
3631 }
3632
Willy Tarreau20b0de52012-12-24 15:45:22 +01003633 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003634 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003635 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3636 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3637 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3638 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003639 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 +01003640 file, linenum, args[0]);
3641 err_code |= ERR_WARN;
3642 }
3643
Willy Tarreauff011f22011-01-06 17:51:27 +01003644 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003645
Willy Tarreauff011f22011-01-06 17:51:27 +01003646 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003647 err_code |= ERR_ALERT | ERR_ABORT;
3648 goto out;
3649 }
3650
Willy Tarreau5002f572014-04-23 01:32:02 +02003651 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003652 err_code |= warnif_cond_conflicts(rule->cond,
3653 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3654 file, linenum);
3655
Willy Tarreauff011f22011-01-06 17:51:27 +01003656 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003657 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003658 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003659 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003660
3661 if (curproxy == &defproxy) {
3662 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666
3667 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003668 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003669 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3670 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003671 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3672 file, linenum, args[0]);
3673 err_code |= ERR_WARN;
3674 }
3675
3676 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3677
3678 if (!rule) {
3679 err_code |= ERR_ALERT | ERR_ABORT;
3680 goto out;
3681 }
3682
3683 err_code |= warnif_cond_conflicts(rule->cond,
3684 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3685 file, linenum);
3686
3687 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3688 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003689 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3690 /* set the header name and length into the proxy structure */
3691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3692 err_code |= ERR_WARN;
3693
3694 if (!*args[1]) {
3695 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3696 file, linenum, args[0]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700
3701 /* set the desired header name */
3702 free(curproxy->server_id_hdr_name);
3703 curproxy->server_id_hdr_name = strdup(args[1]);
3704 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3705 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003706 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003707 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003708
Willy Tarreaub099aca2008-10-12 17:26:37 +02003709 if (curproxy == &defproxy) {
3710 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003713 }
3714
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003715 /* emulate "block" using "http-request block". Since these rules are supposed to
3716 * be processed before all http-request rules, we put them into their own list
3717 * and will insert them at the end.
3718 */
3719 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3720 if (!rule) {
3721 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003722 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003723 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003724 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3725 err_code |= warnif_cond_conflicts(rule->cond,
3726 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3727 file, linenum);
3728 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003729
3730 if (!already_warned(WARN_BLOCK_DEPRECATED))
3731 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]);
3732
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003733 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003734 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003735 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003736
Cyril Bonté99ed3272010-01-24 23:29:44 +01003737 if (curproxy == &defproxy) {
3738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
3741 }
3742
Willy Tarreaube4653b2015-05-28 15:26:58 +02003743 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003744 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3745 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003748 }
3749
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003750 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003751 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003752 err_code |= warnif_cond_conflicts(rule->cond,
3753 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3754 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003755 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003756 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003757 struct switching_rule *rule;
3758
Willy Tarreaub099aca2008-10-12 17:26:37 +02003759 if (curproxy == &defproxy) {
3760 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003763 }
3764
Willy Tarreau55ea7572007-06-17 19:56:27 +02003765 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003767
3768 if (*(args[1]) == 0) {
3769 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003772 }
3773
Willy Tarreauf51658d2014-04-23 01:21:56 +02003774 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3775 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3776 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3777 file, linenum, errmsg);
3778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
3780 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003781
Willy Tarreauf51658d2014-04-23 01:21:56 +02003782 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003783 }
3784
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003785 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003786 if (!rule) {
3787 Alert("Out of memory error.\n");
3788 goto out;
3789 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003790 rule->cond = cond;
3791 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003792 rule->line = linenum;
3793 rule->file = strdup(file);
3794 if (!rule->file) {
3795 Alert("Out of memory error.\n");
3796 goto out;
3797 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003798 LIST_INIT(&rule->list);
3799 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3800 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003801 else if (strcmp(args[0], "use-server") == 0) {
3802 struct server_rule *rule;
3803
3804 if (curproxy == &defproxy) {
3805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809
3810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3811 err_code |= ERR_WARN;
3812
3813 if (*(args[1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818
3819 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3820 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3821 file, linenum, args[0]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003826 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3827 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3828 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003833 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003834
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003835 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003836 rule->cond = cond;
3837 rule->srv.name = strdup(args[1]);
3838 LIST_INIT(&rule->list);
3839 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3840 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3841 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003842 else if ((!strcmp(args[0], "force-persist")) ||
3843 (!strcmp(args[0], "ignore-persist"))) {
3844 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003845
3846 if (curproxy == &defproxy) {
3847 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851
3852 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3853 err_code |= ERR_WARN;
3854
Willy Tarreauef6494c2010-01-28 17:12:36 +01003855 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003856 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3857 file, linenum, args[0]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003862 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3863 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3864 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
3867 }
3868
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003869 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3870 * where force-persist is applied.
3871 */
3872 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003873
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003874 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003875 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003876 if (!strcmp(args[0], "force-persist")) {
3877 rule->type = PERSIST_TYPE_FORCE;
3878 } else {
3879 rule->type = PERSIST_TYPE_IGNORE;
3880 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003881 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003882 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003883 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003884 else if (!strcmp(args[0], "stick-table")) {
3885 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003886 struct proxy *other;
3887
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003888 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003889 if (other) {
3890 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3891 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003895
Emeric Brun32da3c42010-09-23 18:39:19 +02003896 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003897 curproxy->table.type = (unsigned int)-1;
3898 while (*args[myidx]) {
3899 const char *err;
3900
3901 if (strcmp(args[myidx], "size") == 0) {
3902 myidx++;
3903 if (!*(args[myidx])) {
3904 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3905 file, linenum, args[myidx-1]);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3910 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3911 file, linenum, *err, args[myidx-1]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003915 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003916 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003917 else if (strcmp(args[myidx], "peers") == 0) {
3918 myidx++;
Godbach50523162013-12-11 19:48:57 +08003919 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003920 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3921 file, linenum, args[myidx-1]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
Godbach50523162013-12-11 19:48:57 +08003924 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003925 curproxy->table.peers.name = strdup(args[myidx++]);
3926 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003927 else if (strcmp(args[myidx], "expire") == 0) {
3928 myidx++;
3929 if (!*(args[myidx])) {
3930 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3931 file, linenum, args[myidx-1]);
3932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
3934 }
3935 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3936 if (err) {
3937 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3938 file, linenum, *err, args[myidx-1]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003942 if (val > INT_MAX) {
3943 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3944 file, linenum, val);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003949 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003950 }
3951 else if (strcmp(args[myidx], "nopurge") == 0) {
3952 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003953 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003954 }
3955 else if (strcmp(args[myidx], "type") == 0) {
3956 myidx++;
3957 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3958 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3959 file, linenum, args[myidx]);
3960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
3962 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003963 /* myidx already points to next arg */
3964 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003965 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003966 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003967 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003968
3969 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003970 nw = args[myidx];
3971 while (*nw) {
3972 /* the "store" keyword supports a comma-separated list */
3973 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003974 sa = NULL; /* store arg */
3975 while (*nw && *nw != ',') {
3976 if (*nw == '(') {
3977 *nw = 0;
3978 sa = ++nw;
3979 while (*nw != ')') {
3980 if (!*nw) {
3981 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3982 file, linenum, args[0], cw);
3983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
3985 }
3986 nw++;
3987 }
3988 *nw = '\0';
3989 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003990 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003991 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003992 if (*nw)
3993 *nw++ = '\0';
3994 type = stktable_get_data_type(cw);
3995 if (type < 0) {
3996 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3997 file, linenum, args[0], cw);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
Willy Tarreauac782882010-06-20 10:41:54 +02004001
4002 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4003 switch (err) {
4004 case PE_NONE: break;
4005 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004006 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4007 file, linenum, args[0], cw);
4008 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004009 break;
4010
4011 case PE_ARG_MISSING:
4012 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4013 file, linenum, args[0], cw);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016
4017 case PE_ARG_NOT_USED:
4018 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4019 file, linenum, args[0], cw);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
4022
4023 default:
4024 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4025 file, linenum, args[0], cw);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004028 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004029 }
4030 myidx++;
4031 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004032 else {
4033 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4034 file, linenum, args[myidx]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004038 }
4039
4040 if (!curproxy->table.size) {
4041 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4042 file, linenum);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045 }
4046
4047 if (curproxy->table.type == (unsigned int)-1) {
4048 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4049 file, linenum);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053 }
4054 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004055 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004056 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004057 int myidx = 0;
4058 const char *name = NULL;
4059 int flags;
4060
4061 if (curproxy == &defproxy) {
4062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
4065 }
4066
4067 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4068 err_code |= ERR_WARN;
4069 goto out;
4070 }
4071
4072 myidx++;
4073 if ((strcmp(args[myidx], "store") == 0) ||
4074 (strcmp(args[myidx], "store-request") == 0)) {
4075 myidx++;
4076 flags = STK_IS_STORE;
4077 }
4078 else if (strcmp(args[myidx], "store-response") == 0) {
4079 myidx++;
4080 flags = STK_IS_STORE | STK_ON_RSP;
4081 }
4082 else if (strcmp(args[myidx], "match") == 0) {
4083 myidx++;
4084 flags = STK_IS_MATCH;
4085 }
4086 else if (strcmp(args[myidx], "on") == 0) {
4087 myidx++;
4088 flags = STK_IS_MATCH | STK_IS_STORE;
4089 }
4090 else {
4091 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095
4096 if (*(args[myidx]) == 0) {
4097 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
4101
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004102 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004103 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004104 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004105 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109
4110 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004111 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4112 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4113 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004115 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004116 goto out;
4117 }
4118 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004119 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4120 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4121 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004122 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004123 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 goto out;
4125 }
4126 }
4127
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004128 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004129 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004130
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 if (strcmp(args[myidx], "table") == 0) {
4132 myidx++;
4133 name = args[myidx++];
4134 }
4135
Willy Tarreauef6494c2010-01-28 17:12:36 +01004136 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004137 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4138 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4139 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004140 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004141 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004142 goto out;
4143 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004144 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004145 else if (*(args[myidx])) {
4146 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4147 file, linenum, args[0], args[myidx]);
4148 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004149 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004150 goto out;
4151 }
Emeric Brun97679e72010-09-23 17:56:44 +02004152 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004153 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004154 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004155 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004156
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004157 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 rule->cond = cond;
4159 rule->expr = expr;
4160 rule->flags = flags;
4161 rule->table.name = name ? strdup(name) : NULL;
4162 LIST_INIT(&rule->list);
4163 if (flags & STK_ON_RSP)
4164 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4165 else
4166 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 else if (!strcmp(args[0], "stats")) {
4169 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4170 curproxy->uri_auth = NULL; /* we must detach from the default config */
4171
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004172 if (!*args[1]) {
4173 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004174 } else if (!strcmp(args[1], "admin")) {
4175 struct stats_admin_rule *rule;
4176
4177 if (curproxy == &defproxy) {
4178 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
4182
4183 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4184 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4185 err_code |= ERR_ALERT | ERR_ABORT;
4186 goto out;
4187 }
4188
4189 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4190 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4191 file, linenum, args[0], args[1]);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004195 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4196 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4197 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004202 err_code |= warnif_cond_conflicts(cond,
4203 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4204 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004205
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004206 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004207 rule->cond = cond;
4208 LIST_INIT(&rule->list);
4209 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 } else if (!strcmp(args[1], "uri")) {
4211 if (*(args[2]) == 0) {
4212 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_ABORT;
4218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 }
4220 } else if (!strcmp(args[1], "realm")) {
4221 if (*(args[2]) == 0) {
4222 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_ALERT | ERR_ABORT;
4228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004230 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004231 unsigned interval;
4232
4233 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4234 if (err) {
4235 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4236 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004239 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_ABORT;
4242 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004243 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004244 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004245 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004246
4247 if (curproxy == &defproxy) {
4248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252
4253 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4254 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4255 err_code |= ERR_ALERT | ERR_ABORT;
4256 goto out;
4257 }
4258
Willy Tarreauff011f22011-01-06 17:51:27 +01004259 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004260 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004261 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4262 file, linenum, args[0]);
4263 err_code |= ERR_WARN;
4264 }
4265
Willy Tarreauff011f22011-01-06 17:51:27 +01004266 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004267
Willy Tarreauff011f22011-01-06 17:51:27 +01004268 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004269 err_code |= ERR_ALERT | ERR_ABORT;
4270 goto out;
4271 }
4272
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004273 err_code |= warnif_cond_conflicts(rule->cond,
4274 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4275 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004276 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004277
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 } else if (!strcmp(args[1], "auth")) {
4279 if (*(args[2]) == 0) {
4280 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4284 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004285 err_code |= ERR_ALERT | ERR_ABORT;
4286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 }
4288 } else if (!strcmp(args[1], "scope")) {
4289 if (*(args[2]) == 0) {
4290 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4294 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_ALERT | ERR_ABORT;
4296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 }
4298 } else if (!strcmp(args[1], "enable")) {
4299 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4300 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_ABORT;
4302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004304 } else if (!strcmp(args[1], "hide-version")) {
4305 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_ABORT;
4308 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004309 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004310 } else if (!strcmp(args[1], "show-legends")) {
4311 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4312 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4313 err_code |= ERR_ALERT | ERR_ABORT;
4314 goto out;
4315 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004316 } else if (!strcmp(args[1], "show-node")) {
4317
4318 if (*args[2]) {
4319 int i;
4320 char c;
4321
4322 for (i=0; args[2][i]; i++) {
4323 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004324 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4325 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004326 break;
4327 }
4328
4329 if (!i || args[2][i]) {
4330 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4331 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4332 file, linenum, args[0], args[1]);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336 }
4337
4338 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4339 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4340 err_code |= ERR_ALERT | ERR_ABORT;
4341 goto out;
4342 }
4343 } else if (!strcmp(args[1], "show-desc")) {
4344 char *desc = NULL;
4345
4346 if (*args[2]) {
4347 int i, len=0;
4348 char *d;
4349
Willy Tarreau348acfe2014-04-14 15:00:39 +02004350 for (i = 2; *args[i]; i++)
4351 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004352
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004353 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004354
Willy Tarreau348acfe2014-04-14 15:00:39 +02004355 d += snprintf(d, desc + len - d, "%s", args[2]);
4356 for (i = 3; *args[i]; i++)
4357 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004358 }
4359
4360 if (!*args[2] && !global.desc)
4361 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4362 file, linenum, args[1]);
4363 else {
4364 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4365 free(desc);
4366 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4367 err_code |= ERR_ALERT | ERR_ABORT;
4368 goto out;
4369 }
4370 free(desc);
4371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004373stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004374 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 +01004375 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
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 }
4379 }
4380 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004381 int optnum;
4382
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004383 if (*(args[1]) == '\0') {
4384 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4385 file, linenum, args[0]);
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 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004389
4390 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4391 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004392 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4393 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4394 file, linenum, cfg_opts[optnum].name);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004398 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4399 goto out;
4400
Willy Tarreau93893792009-07-23 13:19:11 +02004401 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4402 err_code |= ERR_WARN;
4403 goto out;
4404 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004405
Willy Tarreau3842f002009-06-14 11:39:52 +02004406 curproxy->no_options &= ~cfg_opts[optnum].val;
4407 curproxy->options &= ~cfg_opts[optnum].val;
4408
4409 switch (kwm) {
4410 case KWM_STD:
4411 curproxy->options |= cfg_opts[optnum].val;
4412 break;
4413 case KWM_NO:
4414 curproxy->no_options |= cfg_opts[optnum].val;
4415 break;
4416 case KWM_DEF: /* already cleared */
4417 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004418 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004419
Willy Tarreau93893792009-07-23 13:19:11 +02004420 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004421 }
4422 }
4423
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004424 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4425 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004426 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4427 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4428 file, linenum, cfg_opts2[optnum].name);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004432 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4433 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004434 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4435 err_code |= ERR_WARN;
4436 goto out;
4437 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004438
Willy Tarreau3842f002009-06-14 11:39:52 +02004439 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4440 curproxy->options2 &= ~cfg_opts2[optnum].val;
4441
4442 switch (kwm) {
4443 case KWM_STD:
4444 curproxy->options2 |= cfg_opts2[optnum].val;
4445 break;
4446 case KWM_NO:
4447 curproxy->no_options2 |= cfg_opts2[optnum].val;
4448 break;
4449 case KWM_DEF: /* already cleared */
4450 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004451 }
Willy Tarreau93893792009-07-23 13:19:11 +02004452 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004453 }
4454 }
4455
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004456 /* HTTP options override each other. They can be cancelled using
4457 * "no option xxx" which only switches to default mode if the mode
4458 * was this one (useful for cancelling options set in defaults
4459 * sections).
4460 */
4461 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004462 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4463 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004464 if (kwm == KWM_STD) {
4465 curproxy->options &= ~PR_O_HTTP_MODE;
4466 curproxy->options |= PR_O_HTTP_PCL;
4467 goto out;
4468 }
4469 else if (kwm == KWM_NO) {
4470 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4471 curproxy->options &= ~PR_O_HTTP_MODE;
4472 goto out;
4473 }
4474 }
4475 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004476 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4477 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004478 if (kwm == KWM_STD) {
4479 curproxy->options &= ~PR_O_HTTP_MODE;
4480 curproxy->options |= PR_O_HTTP_FCL;
4481 goto out;
4482 }
4483 else if (kwm == KWM_NO) {
4484 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4485 curproxy->options &= ~PR_O_HTTP_MODE;
4486 goto out;
4487 }
4488 }
4489 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004490 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4491 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004492 if (kwm == KWM_STD) {
4493 curproxy->options &= ~PR_O_HTTP_MODE;
4494 curproxy->options |= PR_O_HTTP_SCL;
4495 goto out;
4496 }
4497 else if (kwm == KWM_NO) {
4498 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4499 curproxy->options &= ~PR_O_HTTP_MODE;
4500 goto out;
4501 }
4502 }
4503 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004504 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4505 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004506 if (kwm == KWM_STD) {
4507 curproxy->options &= ~PR_O_HTTP_MODE;
4508 curproxy->options |= PR_O_HTTP_KAL;
4509 goto out;
4510 }
4511 else if (kwm == KWM_NO) {
4512 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4513 curproxy->options &= ~PR_O_HTTP_MODE;
4514 goto out;
4515 }
4516 }
4517 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004518 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4519 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004520 if (kwm == KWM_STD) {
4521 curproxy->options &= ~PR_O_HTTP_MODE;
4522 curproxy->options |= PR_O_HTTP_TUN;
4523 goto out;
4524 }
4525 else if (kwm == KWM_NO) {
4526 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4527 curproxy->options &= ~PR_O_HTTP_MODE;
4528 goto out;
4529 }
4530 }
4531
Joseph Lynch726ab712015-05-11 23:25:34 -07004532 /* Redispatch can take an integer argument that control when the
4533 * resispatch occurs. All values are relative to the retries option.
4534 * This can be cancelled using "no option xxx".
4535 */
4536 if (strcmp(args[1], "redispatch") == 0) {
4537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4538 err_code |= ERR_WARN;
4539 goto out;
4540 }
4541
4542 curproxy->no_options &= ~PR_O_REDISP;
4543 curproxy->options &= ~PR_O_REDISP;
4544
4545 switch (kwm) {
4546 case KWM_STD:
4547 curproxy->options |= PR_O_REDISP;
4548 curproxy->redispatch_after = -1;
4549 if(*args[2]) {
4550 curproxy->redispatch_after = atol(args[2]);
4551 }
4552 break;
4553 case KWM_NO:
4554 curproxy->no_options |= PR_O_REDISP;
4555 curproxy->redispatch_after = 0;
4556 break;
4557 case KWM_DEF: /* already cleared */
4558 break;
4559 }
4560 goto out;
4561 }
4562
Willy Tarreau3842f002009-06-14 11:39:52 +02004563 if (kwm != KWM_STD) {
4564 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004565 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004568 }
4569
Emeric Brun3a058f32009-06-30 18:26:00 +02004570 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004571 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004573 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004574 if (*(args[2]) != '\0') {
4575 if (!strcmp(args[2], "clf")) {
4576 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004577 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004578 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004579 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004582 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004583 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4584 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004585 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004586 if (curproxy->conf.logformat_string != default_http_log_format &&
4587 curproxy->conf.logformat_string != default_tcp_log_format &&
4588 curproxy->conf.logformat_string != clf_http_log_format)
4589 free(curproxy->conf.logformat_string);
4590 curproxy->conf.logformat_string = logformat;
4591
4592 free(curproxy->conf.lfs_file);
4593 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4594 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004595 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004596 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004598 if (curproxy->conf.logformat_string != default_http_log_format &&
4599 curproxy->conf.logformat_string != default_tcp_log_format &&
4600 curproxy->conf.logformat_string != clf_http_log_format)
4601 free(curproxy->conf.logformat_string);
4602 curproxy->conf.logformat_string = default_tcp_log_format;
4603
4604 free(curproxy->conf.lfs_file);
4605 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4606 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004607
4608 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4609 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004612 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004613 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004615
William Lallemanddf1425a2015-04-28 20:17:49 +02004616 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4617 goto out;
4618
Willy Tarreau13943ab2006-12-31 00:24:10 +01004619 if (curproxy->cap & PR_CAP_FE)
4620 curproxy->options |= PR_O_TCP_CLI_KA;
4621 if (curproxy->cap & PR_CAP_BE)
4622 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 }
4624 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004626 err_code |= ERR_WARN;
4627
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004629 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004630 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004631 curproxy->options2 &= ~PR_O2_CHK_ANY;
4632 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 if (!*args[2]) { /* no argument */
4634 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4635 curproxy->check_len = strlen(DEF_CHECK_REQ);
4636 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004637 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004638 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004640 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004642 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 if (*args[4])
4644 reqlen += strlen(args[4]);
4645 else
4646 reqlen += strlen("HTTP/1.0");
4647
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004648 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004650 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004652 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4653 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004654 }
4655 else if (!strcmp(args[1], "ssl-hello-chk")) {
4656 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004658 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004659
Willy Tarreaua534fea2008-08-03 12:19:50 +02004660 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004661 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004662 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004663 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004664
4665 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
Willy Tarreau23677902007-05-08 23:50:35 +02004668 else if (!strcmp(args[1], "smtpchk")) {
4669 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004670 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004671 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004672 curproxy->options2 &= ~PR_O2_CHK_ANY;
4673 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004674
4675 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4676 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4677 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4678 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4679 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4680 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004681 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004682 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4683 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4684 } else {
4685 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4686 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4687 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4688 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4689 }
4690 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004691 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4692 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004693 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004694 else if (!strcmp(args[1], "pgsql-check")) {
4695 /* use PostgreSQL request to check servers' health */
4696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4697 err_code |= ERR_WARN;
4698
4699 free(curproxy->check_req);
4700 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004701 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004702 curproxy->options2 |= PR_O2_PGSQL_CHK;
4703
4704 if (*(args[2])) {
4705 int cur_arg = 2;
4706
4707 while (*(args[cur_arg])) {
4708 if (strcmp(args[cur_arg], "user") == 0) {
4709 char * packet;
4710 uint32_t packet_len;
4711 uint32_t pv;
4712
4713 /* suboption header - needs additional argument for it */
4714 if (*(args[cur_arg+1]) == 0) {
4715 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4716 file, linenum, args[0], args[1], args[cur_arg]);
4717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
4720
4721 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4722 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4723 pv = htonl(0x30000); /* protocol version 3.0 */
4724
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004725 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004726
4727 memcpy(packet + 4, &pv, 4);
4728
4729 /* copy "user" */
4730 memcpy(packet + 8, "user", 4);
4731
4732 /* copy username */
4733 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4734
4735 free(curproxy->check_req);
4736 curproxy->check_req = packet;
4737 curproxy->check_len = packet_len;
4738
4739 packet_len = htonl(packet_len);
4740 memcpy(packet, &packet_len, 4);
4741 cur_arg += 2;
4742 } else {
4743 /* unknown suboption - catchall */
4744 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4745 file, linenum, args[0], args[1]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
4749 } /* end while loop */
4750 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004751 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4752 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004753 }
4754
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004755 else if (!strcmp(args[1], "redis-check")) {
4756 /* use REDIS PING request to check servers' health */
4757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4758 err_code |= ERR_WARN;
4759
4760 free(curproxy->check_req);
4761 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004762 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004763 curproxy->options2 |= PR_O2_REDIS_CHK;
4764
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004765 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004766 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4767 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004768
4769 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4770 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004771 }
4772
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004773 else if (!strcmp(args[1], "mysql-check")) {
4774 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4776 err_code |= ERR_WARN;
4777
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004778 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004779 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004780 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004781 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004782
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004783 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004784 * const char mysql40_client_auth_pkt[] = {
4785 * "\x0e\x00\x00" // packet length
4786 * "\x01" // packet number
4787 * "\x00\x00" // client capabilities
4788 * "\x00\x00\x01" // max packet
4789 * "haproxy\x00" // username (null terminated string)
4790 * "\x00" // filler (always 0x00)
4791 * "\x01\x00\x00" // packet length
4792 * "\x00" // packet number
4793 * "\x01" // COM_QUIT command
4794 * };
4795 */
4796
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004797 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4798 * const char mysql41_client_auth_pkt[] = {
4799 * "\x0e\x00\x00\" // packet length
4800 * "\x01" // packet number
4801 * "\x00\x00\x00\x00" // client capabilities
4802 * "\x00\x00\x00\x01" // max packet
4803 * "\x21" // character set (UTF-8)
4804 * char[23] // All zeroes
4805 * "haproxy\x00" // username (null terminated string)
4806 * "\x00" // filler (always 0x00)
4807 * "\x01\x00\x00" // packet length
4808 * "\x00" // packet number
4809 * "\x01" // COM_QUIT command
4810 * };
4811 */
4812
4813
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004814 if (*(args[2])) {
4815 int cur_arg = 2;
4816
4817 while (*(args[cur_arg])) {
4818 if (strcmp(args[cur_arg], "user") == 0) {
4819 char *mysqluser;
4820 int packetlen, reqlen, userlen;
4821
4822 /* suboption header - needs additional argument for it */
4823 if (*(args[cur_arg+1]) == 0) {
4824 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4825 file, linenum, args[0], args[1], args[cur_arg]);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
4829 mysqluser = args[cur_arg + 1];
4830 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004831
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004832 if (*(args[cur_arg+2])) {
4833 if (!strcmp(args[cur_arg+2], "post-41")) {
4834 packetlen = userlen + 7 + 27;
4835 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004836
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004837 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004838 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004839 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004840
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004841 snprintf(curproxy->check_req, 4, "%c%c%c",
4842 ((unsigned char) packetlen & 0xff),
4843 ((unsigned char) (packetlen >> 8) & 0xff),
4844 ((unsigned char) (packetlen >> 16) & 0xff));
4845
4846 curproxy->check_req[3] = 1;
4847 curproxy->check_req[5] = 130;
4848 curproxy->check_req[11] = 1;
4849 curproxy->check_req[12] = 33;
4850 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4851 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4852 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4853 cur_arg += 3;
4854 } else {
4855 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
4858 }
4859 } else {
4860 packetlen = userlen + 7;
4861 reqlen = packetlen + 9;
4862
4863 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004864 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004865 curproxy->check_len = reqlen;
4866
4867 snprintf(curproxy->check_req, 4, "%c%c%c",
4868 ((unsigned char) packetlen & 0xff),
4869 ((unsigned char) (packetlen >> 8) & 0xff),
4870 ((unsigned char) (packetlen >> 16) & 0xff));
4871
4872 curproxy->check_req[3] = 1;
4873 curproxy->check_req[5] = 128;
4874 curproxy->check_req[8] = 1;
4875 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4876 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4877 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4878 cur_arg += 2;
4879 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004880 } else {
4881 /* unknown suboption - catchall */
4882 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4883 file, linenum, args[0], args[1]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 } /* end while loop */
4888 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004889 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004890 else if (!strcmp(args[1], "ldap-check")) {
4891 /* use LDAP request to check servers' health */
4892 free(curproxy->check_req);
4893 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004894 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004895 curproxy->options2 |= PR_O2_LDAP_CHK;
4896
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004897 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004898 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4899 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004900 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4901 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004902 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004903 else if (!strcmp(args[1], "spop-check")) {
4904 if (curproxy == &defproxy) {
4905 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4906 file, linenum, args[0], args[1]);
4907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909 }
4910 if (curproxy->cap & PR_CAP_FE) {
4911 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4912 file, linenum, args[0], args[1]);
4913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915 }
4916
4917 /* use SPOE request to check servers' health */
4918 free(curproxy->check_req);
4919 curproxy->check_req = NULL;
4920 curproxy->options2 &= ~PR_O2_CHK_ANY;
4921 curproxy->options2 |= PR_O2_SPOP_CHK;
4922
4923 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
4924 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
4927 }
4928 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4929 goto out;
4930 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004931 else if (!strcmp(args[1], "tcp-check")) {
4932 /* use raw TCPCHK send/expect to check servers' health */
4933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4934 err_code |= ERR_WARN;
4935
4936 free(curproxy->check_req);
4937 curproxy->check_req = NULL;
4938 curproxy->options2 &= ~PR_O2_CHK_ANY;
4939 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004940 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4941 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004942 }
Simon Horman98637e52014-06-20 12:30:16 +09004943 else if (!strcmp(args[1], "external-check")) {
4944 /* excute an external command to check servers' health */
4945 free(curproxy->check_req);
4946 curproxy->check_req = NULL;
4947 curproxy->options2 &= ~PR_O2_CHK_ANY;
4948 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004949 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4950 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004951 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004952 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004953 int cur_arg;
4954
4955 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4956 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004957 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004958
Willy Tarreau87cf5142011-08-19 22:57:24 +02004959 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004960
4961 free(curproxy->fwdfor_hdr_name);
4962 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4963 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4964
4965 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4966 cur_arg = 2;
4967 while (*(args[cur_arg])) {
4968 if (!strcmp(args[cur_arg], "except")) {
4969 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004970 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004971 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4972 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004975 }
4976 /* flush useless bits */
4977 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004978 cur_arg += 2;
4979 } else if (!strcmp(args[cur_arg], "header")) {
4980 /* suboption header - needs additional argument for it */
4981 if (*(args[cur_arg+1]) == 0) {
4982 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4983 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004986 }
4987 free(curproxy->fwdfor_hdr_name);
4988 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4989 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4990 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004991 } else if (!strcmp(args[cur_arg], "if-none")) {
4992 curproxy->options &= ~PR_O_FF_ALWAYS;
4993 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004994 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004995 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004996 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004997 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005000 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005001 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005002 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005003 else if (!strcmp(args[1], "originalto")) {
5004 int cur_arg;
5005
5006 /* insert x-original-to field, but not for the IP address listed as an except.
5007 * set default options (ie: bitfield, header name, etc)
5008 */
5009
5010 curproxy->options |= PR_O_ORGTO;
5011
5012 free(curproxy->orgto_hdr_name);
5013 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5014 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5015
Willy Tarreau87cf5142011-08-19 22:57:24 +02005016 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005017 cur_arg = 2;
5018 while (*(args[cur_arg])) {
5019 if (!strcmp(args[cur_arg], "except")) {
5020 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005021 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 +02005022 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5023 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005026 }
5027 /* flush useless bits */
5028 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5029 cur_arg += 2;
5030 } else if (!strcmp(args[cur_arg], "header")) {
5031 /* suboption header - needs additional argument for it */
5032 if (*(args[cur_arg+1]) == 0) {
5033 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5034 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005037 }
5038 free(curproxy->orgto_hdr_name);
5039 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5040 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5041 cur_arg += 2;
5042 } else {
5043 /* unknown suboption - catchall */
5044 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5045 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005048 }
5049 } /* end while loop */
5050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 else {
5052 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreau93893792009-07-23 13:19:11 +02005056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005058 else if (!strcmp(args[0], "default_backend")) {
5059 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005061
5062 if (*(args[1]) == 0) {
5063 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005066 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005067 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005068 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005069
5070 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5071 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005074 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005075 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005076
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005077 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5078 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 +01005079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 /* enable reconnections to dispatch */
5082 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005083
5084 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005087 else if (!strcmp(args[0], "http-reuse")) {
5088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5089 err_code |= ERR_WARN;
5090
5091 if (strcmp(args[1], "never") == 0) {
5092 /* enable a graceful server shutdown on an HTTP 404 response */
5093 curproxy->options &= ~PR_O_REUSE_MASK;
5094 curproxy->options |= PR_O_REUSE_NEVR;
5095 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5096 goto out;
5097 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005098 else if (strcmp(args[1], "safe") == 0) {
5099 /* enable a graceful server shutdown on an HTTP 404 response */
5100 curproxy->options &= ~PR_O_REUSE_MASK;
5101 curproxy->options |= PR_O_REUSE_SAFE;
5102 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5103 goto out;
5104 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005105 else if (strcmp(args[1], "aggressive") == 0) {
5106 curproxy->options &= ~PR_O_REUSE_MASK;
5107 curproxy->options |= PR_O_REUSE_AGGR;
5108 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5109 goto out;
5110 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005111 else if (strcmp(args[1], "always") == 0) {
5112 /* enable a graceful server shutdown on an HTTP 404 response */
5113 curproxy->options &= ~PR_O_REUSE_MASK;
5114 curproxy->options |= PR_O_REUSE_ALWS;
5115 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5116 goto out;
5117 }
5118 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005119 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
5123 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005124 else if (!strcmp(args[0], "http-check")) {
5125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005127
5128 if (strcmp(args[1], "disable-on-404") == 0) {
5129 /* enable a graceful server shutdown on an HTTP 404 response */
5130 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005131 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5132 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005133 }
Willy Tarreauef781042010-01-27 11:53:01 +01005134 else if (strcmp(args[1], "send-state") == 0) {
5135 /* enable emission of the apparent state of a server in HTTP checks */
5136 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005137 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5138 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005139 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005140 else if (strcmp(args[1], "expect") == 0) {
5141 const char *ptr_arg;
5142 int cur_arg;
5143
5144 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5145 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
5149
5150 cur_arg = 2;
5151 /* consider exclamation marks, sole or at the beginning of a word */
5152 while (*(ptr_arg = args[cur_arg])) {
5153 while (*ptr_arg == '!') {
5154 curproxy->options2 ^= PR_O2_EXP_INV;
5155 ptr_arg++;
5156 }
5157 if (*ptr_arg)
5158 break;
5159 cur_arg++;
5160 }
5161 /* now ptr_arg points to the beginning of a word past any possible
5162 * exclamation mark, and cur_arg is the argument which holds this word.
5163 */
5164 if (strcmp(ptr_arg, "status") == 0) {
5165 if (!*(args[cur_arg + 1])) {
5166 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5167 file, linenum, args[0], args[1], ptr_arg);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
5171 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005172 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005173 curproxy->expect_str = strdup(args[cur_arg + 1]);
5174 }
5175 else if (strcmp(ptr_arg, "string") == 0) {
5176 if (!*(args[cur_arg + 1])) {
5177 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5178 file, linenum, args[0], args[1], ptr_arg);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005183 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005184 curproxy->expect_str = strdup(args[cur_arg + 1]);
5185 }
5186 else if (strcmp(ptr_arg, "rstatus") == 0) {
5187 if (!*(args[cur_arg + 1])) {
5188 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5189 file, linenum, args[0], args[1], ptr_arg);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005194 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005195 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005196 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005197 free(curproxy->expect_regex);
5198 curproxy->expect_regex = NULL;
5199 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005200 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005201 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5202 error = NULL;
5203 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5204 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5205 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5206 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
5210 }
5211 else if (strcmp(ptr_arg, "rstring") == 0) {
5212 if (!*(args[cur_arg + 1])) {
5213 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5214 file, linenum, args[0], args[1], ptr_arg);
5215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
5217 }
5218 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005219 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005220 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005221 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005222 free(curproxy->expect_regex);
5223 curproxy->expect_regex = NULL;
5224 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005225 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005226 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5227 error = NULL;
5228 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5229 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5230 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5231 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
5235 }
5236 else {
5237 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5238 file, linenum, args[0], args[1], ptr_arg);
5239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241 }
5242 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005243 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005244 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 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005247 }
5248 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005249 else if (!strcmp(args[0], "tcp-check")) {
5250 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5251 err_code |= ERR_WARN;
5252
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005253 if (strcmp(args[1], "comment") == 0) {
5254 int cur_arg;
5255 struct tcpcheck_rule *tcpcheck;
5256
5257 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005258 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005259 tcpcheck->action = TCPCHK_ACT_COMMENT;
5260
5261 if (!*args[cur_arg + 1]) {
5262 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5263 file, linenum, args[cur_arg]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
5267
5268 tcpcheck->comment = strdup(args[cur_arg + 1]);
5269
5270 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005271 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5272 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005273 }
5274 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005275 const char *ptr_arg;
5276 int cur_arg;
5277 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005278
5279 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005280 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5281 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5282 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5283 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5284 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005285
Willy Tarreau5581c272015-05-13 12:24:53 +02005286 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5287 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5288 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5289 file, linenum);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005292 }
5293
5294 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005295 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005296 tcpcheck->action = TCPCHK_ACT_CONNECT;
5297
5298 /* parsing each parameters to fill up the rule */
5299 while (*(ptr_arg = args[cur_arg])) {
5300 /* tcp port */
5301 if (strcmp(args[cur_arg], "port") == 0) {
5302 if ( (atol(args[cur_arg + 1]) > 65535) ||
5303 (atol(args[cur_arg + 1]) < 1) ){
5304 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5305 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
5308 }
5309 tcpcheck->port = atol(args[cur_arg + 1]);
5310 cur_arg += 2;
5311 }
5312 /* send proxy protocol */
5313 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5314 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5315 cur_arg++;
5316 }
5317#ifdef USE_OPENSSL
5318 else if (strcmp(args[cur_arg], "ssl") == 0) {
5319 curproxy->options |= PR_O_TCPCHK_SSL;
5320 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5321 cur_arg++;
5322 }
5323#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005324 /* comment for this tcpcheck line */
5325 else if (strcmp(args[cur_arg], "comment") == 0) {
5326 if (!*args[cur_arg + 1]) {
5327 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5328 file, linenum, args[cur_arg]);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332 tcpcheck->comment = strdup(args[cur_arg + 1]);
5333 cur_arg += 2;
5334 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005335 else {
5336#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005337 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 +01005338#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005339 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 +01005340#endif /* USE_OPENSSL */
5341 file, linenum, args[0], args[1], args[cur_arg]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
5346 }
5347
5348 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5349 }
5350 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005351 if (! *(args[2]) ) {
5352 /* SEND string expected */
5353 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5354 file, linenum, args[0], args[1], args[2]);
5355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 } else {
5358 struct tcpcheck_rule *tcpcheck;
5359
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005360 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005361
5362 tcpcheck->action = TCPCHK_ACT_SEND;
5363 tcpcheck->string_len = strlen(args[2]);
5364 tcpcheck->string = strdup(args[2]);
5365 tcpcheck->expect_regex = NULL;
5366
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005367 /* comment for this tcpcheck line */
5368 if (strcmp(args[3], "comment") == 0) {
5369 if (!*args[4]) {
5370 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5371 file, linenum, args[3]);
5372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
5374 }
5375 tcpcheck->comment = strdup(args[4]);
5376 }
5377
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005378 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5379 }
5380 }
5381 else if (strcmp(args[1], "send-binary") == 0) {
5382 if (! *(args[2]) ) {
5383 /* SEND binary string expected */
5384 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5385 file, linenum, args[0], args[1], args[2]);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 } else {
5389 struct tcpcheck_rule *tcpcheck;
5390 char *err = NULL;
5391
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005392 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005393
5394 tcpcheck->action = TCPCHK_ACT_SEND;
5395 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5396 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5397 file, linenum, args[0], args[1], args[2], err);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401 tcpcheck->expect_regex = NULL;
5402
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005403 /* comment for this tcpcheck line */
5404 if (strcmp(args[3], "comment") == 0) {
5405 if (!*args[4]) {
5406 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5407 file, linenum, args[3]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411 tcpcheck->comment = strdup(args[4]);
5412 }
5413
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005414 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5415 }
5416 }
5417 else if (strcmp(args[1], "expect") == 0) {
5418 const char *ptr_arg;
5419 int cur_arg;
5420 int inverse = 0;
5421
5422 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5423 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
5427
5428 cur_arg = 2;
5429 /* consider exclamation marks, sole or at the beginning of a word */
5430 while (*(ptr_arg = args[cur_arg])) {
5431 while (*ptr_arg == '!') {
5432 inverse = !inverse;
5433 ptr_arg++;
5434 }
5435 if (*ptr_arg)
5436 break;
5437 cur_arg++;
5438 }
5439 /* now ptr_arg points to the beginning of a word past any possible
5440 * exclamation mark, and cur_arg is the argument which holds this word.
5441 */
5442 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005443 struct tcpcheck_rule *tcpcheck;
5444 char *err = NULL;
5445
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005446 if (!*(args[cur_arg + 1])) {
5447 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5448 file, linenum, args[0], args[1], ptr_arg);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005453 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454
5455 tcpcheck->action = TCPCHK_ACT_EXPECT;
5456 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5457 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5458 file, linenum, args[0], args[1], args[2], err);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462 tcpcheck->expect_regex = NULL;
5463 tcpcheck->inverse = inverse;
5464
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005465 /* tcpcheck comment */
5466 cur_arg += 2;
5467 if (strcmp(args[cur_arg], "comment") == 0) {
5468 if (!*args[cur_arg + 1]) {
5469 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5470 file, linenum, args[cur_arg + 1]);
5471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
5474 tcpcheck->comment = strdup(args[cur_arg + 1]);
5475 }
5476
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005477 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5478 }
5479 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005480 struct tcpcheck_rule *tcpcheck;
5481
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005482 if (!*(args[cur_arg + 1])) {
5483 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5484 file, linenum, args[0], args[1], ptr_arg);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005488
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005489 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005490
5491 tcpcheck->action = TCPCHK_ACT_EXPECT;
5492 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5493 tcpcheck->string = strdup(args[cur_arg + 1]);
5494 tcpcheck->expect_regex = NULL;
5495 tcpcheck->inverse = inverse;
5496
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005497 /* tcpcheck comment */
5498 cur_arg += 2;
5499 if (strcmp(args[cur_arg], "comment") == 0) {
5500 if (!*args[cur_arg + 1]) {
5501 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5502 file, linenum, args[cur_arg + 1]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 tcpcheck->comment = strdup(args[cur_arg + 1]);
5507 }
5508
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005509 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5510 }
5511 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005512 struct tcpcheck_rule *tcpcheck;
5513
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005514 if (!*(args[cur_arg + 1])) {
5515 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5516 file, linenum, args[0], args[1], ptr_arg);
5517 err_code |= ERR_ALERT | ERR_FATAL;
5518 goto out;
5519 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005520
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005521 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005522
5523 tcpcheck->action = TCPCHK_ACT_EXPECT;
5524 tcpcheck->string_len = 0;
5525 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005526 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5527 error = NULL;
5528 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5529 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5530 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5531 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535 tcpcheck->inverse = inverse;
5536
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005537 /* tcpcheck comment */
5538 cur_arg += 2;
5539 if (strcmp(args[cur_arg], "comment") == 0) {
5540 if (!*args[cur_arg + 1]) {
5541 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5542 file, linenum, args[cur_arg + 1]);
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
5545 }
5546 tcpcheck->comment = strdup(args[cur_arg + 1]);
5547 }
5548
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005549 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5550 }
5551 else {
5552 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5553 file, linenum, args[0], args[1], ptr_arg);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557 }
5558 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005559 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005564 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005565 if (curproxy == &defproxy) {
5566 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005569 }
5570
Willy Tarreaub80c2302007-11-30 20:51:32 +01005571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005572 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005573
5574 if (strcmp(args[1], "fail") == 0) {
5575 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005576 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005577 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5578 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005581 }
5582
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005583 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5584 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5585 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005588 }
5589 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5590 }
5591 else {
5592 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005595 }
5596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597#ifdef TPROXY
5598 else if (!strcmp(args[0], "transparent")) {
5599 /* enable transparent proxy connections */
5600 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005601 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 }
5604#endif
5605 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005606 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005607 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005608
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 if (*(args[1]) == 0) {
5610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 }
5614 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005615 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005618 else if (!strcmp(args[0], "backlog")) { /* backlog */
5619 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005620 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005621
5622 if (*(args[1]) == 0) {
5623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005626 }
5627 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005628 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5629 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005630 }
Willy Tarreau86034312006-12-29 00:10:33 +01005631 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005634
Willy Tarreau86034312006-12-29 00:10:33 +01005635 if (*(args[1]) == 0) {
5636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005639 }
5640 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005641 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5642 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5645 if (*(args[1]) == 0) {
5646 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005650 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5651 if (err) {
5652 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5653 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005656 }
5657 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005658 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
5661 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005662 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005663 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005664 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005665
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 if (curproxy == &defproxy) {
5667 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005671 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005673
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005674 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005675 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005676 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005677 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005678 goto out;
5679 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005680
5681 proto = protocol_by_family(sk->ss_family);
5682 if (!proto || !proto->connect) {
5683 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5684 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
5687 }
5688
5689 if (port1 != port2) {
5690 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5691 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005692 err_code |= ERR_ALERT | ERR_FATAL;
5693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005695
5696 if (!port1) {
5697 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5698 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005702
William Lallemanddf1425a2015-04-28 20:17:49 +02005703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5704 goto out;
5705
Willy Tarreaud5191e72010-02-09 20:50:45 +01005706 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005707 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 }
5709 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005712
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005713 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5714 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005719 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005720 /**
5721 * The syntax for hash-type config element is
5722 * hash-type {map-based|consistent} [[<algo>] avalanche]
5723 *
5724 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5725 */
5726 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005727
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5729 err_code |= ERR_WARN;
5730
5731 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005732 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5733 }
5734 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005735 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5736 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005737 else if (strcmp(args[1], "avalanche") == 0) {
5738 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]);
5739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005741 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005742 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005743 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
Bhaskar98634f02013-10-29 23:30:51 -04005747
5748 /* set the hash function to use */
5749 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005750 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005751 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005752
5753 /* if consistent with no argument, then avalanche modifier is also applied */
5754 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5755 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005756 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005757 /* set the hash function */
5758 if (!strcmp(args[2], "sdbm")) {
5759 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5760 }
5761 else if (!strcmp(args[2], "djb2")) {
5762 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005763 }
5764 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005765 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005766 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005767 else if (!strcmp(args[2], "crc32")) {
5768 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5769 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005770 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005771 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 -05005772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775
5776 /* set the hash modifier */
5777 if (!strcmp(args[3], "avalanche")) {
5778 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5779 }
5780 else if (*args[3]) {
5781 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
5784 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005785 }
William Lallemanda73203e2012-03-12 12:48:57 +01005786 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005787 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5788 if (*(args[1]) == 0) {
5789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5794 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5795 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
5798 }
5799 }
William Lallemanda73203e2012-03-12 12:48:57 +01005800 else if (strcmp(args[0], "unique-id-format") == 0) {
5801 if (!*(args[1])) {
5802 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805 }
William Lallemand3203ff42012-11-11 17:30:56 +01005806 if (*(args[2])) {
5807 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
5810 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005811 free(curproxy->conf.uniqueid_format_string);
5812 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005813
Willy Tarreau62a61232013-04-12 18:13:46 +02005814 free(curproxy->conf.uif_file);
5815 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5816 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005817 }
William Lallemanda73203e2012-03-12 12:48:57 +01005818
5819 else if (strcmp(args[0], "unique-id-header") == 0) {
5820 if (!*(args[1])) {
5821 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
5824 }
5825 free(curproxy->header_unique_id);
5826 curproxy->header_unique_id = strdup(args[1]);
5827 }
5828
William Lallemand723b73a2012-02-08 16:37:49 +01005829 else if (strcmp(args[0], "log-format") == 0) {
5830 if (!*(args[1])) {
5831 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
5834 }
William Lallemand3203ff42012-11-11 17:30:56 +01005835 if (*(args[2])) {
5836 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
5839 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005840
Willy Tarreau62a61232013-04-12 18:13:46 +02005841 if (curproxy->conf.logformat_string != default_http_log_format &&
5842 curproxy->conf.logformat_string != default_tcp_log_format &&
5843 curproxy->conf.logformat_string != clf_http_log_format)
5844 free(curproxy->conf.logformat_string);
5845 curproxy->conf.logformat_string = strdup(args[1]);
5846
5847 free(curproxy->conf.lfs_file);
5848 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5849 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005850
5851 /* get a chance to improve log-format error reporting by
5852 * reporting the correct line-number when possible.
5853 */
5854 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5855 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5856 file, linenum, curproxy->id);
5857 err_code |= ERR_WARN;
5858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005860 else if (!strcmp(args[0], "log-format-sd")) {
5861 if (!*(args[1])) {
5862 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
5865 }
5866 if (*(args[2])) {
5867 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
5871
5872 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5873 free(curproxy->conf.logformat_sd_string);
5874 curproxy->conf.logformat_sd_string = strdup(args[1]);
5875
5876 free(curproxy->conf.lfsd_file);
5877 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5878 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5879
5880 /* get a chance to improve log-format-sd error reporting by
5881 * reporting the correct line-number when possible.
5882 */
5883 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5884 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5885 file, linenum, curproxy->id);
5886 err_code |= ERR_WARN;
5887 }
5888 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005889 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5890 if (*(args[1]) == 0) {
5891 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005895 chunk_destroy(&curproxy->log_tag);
5896 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005897 }
William Lallemand0f99e342011-10-12 17:50:54 +02005898 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5899 /* delete previous herited or defined syslog servers */
5900 struct logsrv *back;
5901
5902 if (*(args[1]) != 0) {
5903 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907
William Lallemand723b73a2012-02-08 16:37:49 +01005908 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5909 LIST_DEL(&tmplogsrv->list);
5910 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005911 }
5912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005914 struct logsrv *logsrv;
5915
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005917 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005918 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005919 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005920 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005921 LIST_INIT(&node->list);
5922 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
5925 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005926 struct sockaddr_storage *sk;
5927 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005928 int arg = 0;
5929 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005930
Vincent Bernat02779b62016-04-03 13:48:43 +02005931 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932
Willy Tarreau18324f52014-06-27 18:10:07 +02005933 /* just after the address, a length may be specified */
5934 if (strcmp(args[arg+2], "len") == 0) {
5935 len = atoi(args[arg+3]);
5936 if (len < 80 || len > 65535) {
5937 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5938 file, linenum, args[arg+3]);
5939 err_code |= ERR_ALERT | ERR_FATAL;
5940 goto out;
5941 }
5942 logsrv->maxlen = len;
5943
5944 /* skip these two args */
5945 arg += 2;
5946 }
5947 else
5948 logsrv->maxlen = MAX_SYSLOG_LEN;
5949
5950 if (logsrv->maxlen > global.max_syslog_len) {
5951 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02005952 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
5953 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
5954 logline = my_realloc2(logline, global.max_syslog_len + 1);
5955 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005956 }
5957
Dragan Dosen1322d092015-09-22 16:05:32 +02005958 /* after the length, a format may be specified */
5959 if (strcmp(args[arg+2], "format") == 0) {
5960 logsrv->format = get_log_format(args[arg+3]);
5961 if (logsrv->format < 0) {
5962 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5963 err_code |= ERR_ALERT | ERR_FATAL;
5964 goto out;
5965 }
5966
5967 /* skip these two args */
5968 arg += 2;
5969 }
5970
William Lallemanddf1425a2015-04-28 20:17:49 +02005971 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5972 goto out;
5973
Willy Tarreau18324f52014-06-27 18:10:07 +02005974 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005975 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005976 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
5979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
5981
William Lallemand0f99e342011-10-12 17:50:54 +02005982 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005983 if (*(args[arg+3])) {
5984 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005985 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005986 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
5991 }
5992
William Lallemand0f99e342011-10-12 17:50:54 +02005993 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005994 if (*(args[arg+4])) {
5995 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005996 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005997 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006001 }
6002 }
6003
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006004 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006005 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006006 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006008 goto out;
6009 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006010
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006011 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006012
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006013 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006014 if (port1 != port2) {
6015 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6016 file, linenum, args[0], args[1]);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
6020
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006021 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006022 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 }
William Lallemand0f99e342011-10-12 17:50:54 +02006024
6025 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 }
6027 else {
6028 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6029 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006032 }
6033 }
6034 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006035 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006036 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006037 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006039
Willy Tarreau977b8e42006-12-29 14:19:17 +01006040 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006041 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006042
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006044 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6045 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006049
6050 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006051 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6052 free(curproxy->conn_src.iface_name);
6053 curproxy->conn_src.iface_name = NULL;
6054 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006055
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006056 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006057 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006058 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006059 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006060 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006061 goto out;
6062 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006063
6064 proto = protocol_by_family(sk->ss_family);
6065 if (!proto || !proto->connect) {
6066 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006067 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006071
6072 if (port1 != port2) {
6073 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6074 file, linenum, args[0], args[1]);
6075 err_code |= ERR_ALERT | ERR_FATAL;
6076 goto out;
6077 }
6078
Willy Tarreauef9a3602012-12-08 22:29:20 +01006079 curproxy->conn_src.source_addr = *sk;
6080 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006081
6082 cur_arg = 2;
6083 while (*(args[cur_arg])) {
6084 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006085#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006086 if (!*args[cur_arg + 1]) {
6087 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6088 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006089 err_code |= ERR_ALERT | ERR_FATAL;
6090 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006091 }
6092
6093 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006094 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6095 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006096 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006097 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6098 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006099 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6100 char *name, *end;
6101
6102 name = args[cur_arg+1] + 7;
6103 while (isspace(*name))
6104 name++;
6105
6106 end = name;
6107 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6108 end++;
6109
Willy Tarreauef9a3602012-12-08 22:29:20 +01006110 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6111 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6112 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6113 curproxy->conn_src.bind_hdr_len = end - name;
6114 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6115 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6116 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006117
6118 /* now look for an occurrence number */
6119 while (isspace(*end))
6120 end++;
6121 if (*end == ',') {
6122 end++;
6123 name = end;
6124 if (*end == '-')
6125 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006126 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006127 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006128 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006129 }
6130
Willy Tarreauef9a3602012-12-08 22:29:20 +01006131 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006132 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6133 " occurrences values smaller than %d.\n",
6134 file, linenum, MAX_HDR_HISTORY);
6135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006138 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006139 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006140
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006141 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006142 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006143 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006144 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006146 goto out;
6147 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006148
6149 proto = protocol_by_family(sk->ss_family);
6150 if (!proto || !proto->connect) {
6151 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6152 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006156
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006157 if (port1 != port2) {
6158 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6159 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
6162 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006163 curproxy->conn_src.tproxy_addr = *sk;
6164 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006165 }
6166 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006167#else /* no TPROXY support */
6168 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006169 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006170 err_code |= ERR_ALERT | ERR_FATAL;
6171 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006172#endif
6173 cur_arg += 2;
6174 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006175 }
6176
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6178#ifdef SO_BINDTODEVICE
6179 if (!*args[cur_arg + 1]) {
6180 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006184 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006185 free(curproxy->conn_src.iface_name);
6186 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6187 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006188 global.last_checks |= LSTCHK_NETADM;
6189#else
6190 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6191 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006192 err_code |= ERR_ALERT | ERR_FATAL;
6193 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006194#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006195 cur_arg += 2;
6196 continue;
6197 }
6198 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006199 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006204 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6205 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6206 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006210 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006211 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006217
6218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006219 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006220 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 }
6224 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006226 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006233 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
6238 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006240 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 }
6245 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006247 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006252 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006254 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006257 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006259 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006260 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006263 err_code |= ERR_ALERT | ERR_FATAL;
6264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006266
6267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006268 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 }
6273 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006275 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 }
6280 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006282 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 }
6287 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006289 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
6294 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006296 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006301 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006303 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006306 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006309 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006310
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 if (curproxy == &defproxy) {
6312 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006313 err_code |= ERR_ALERT | ERR_FATAL;
6314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006316 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006317 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 if (*(args[1]) == 0) {
6320 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006324
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006325 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006326 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6327 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6328 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006329 err_code |= ERR_ALERT | ERR_FATAL;
6330 goto out;
6331 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006332 err_code |= warnif_cond_conflicts(cond,
6333 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6334 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006335 }
6336 else if (*args[2]) {
6337 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6338 file, linenum, args[0], args[2]);
6339 err_code |= ERR_ALERT | ERR_FATAL;
6340 goto out;
6341 }
6342
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006343 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006344 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006345 wl->s = strdup(args[1]);
6346 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006347 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6352 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006353 err_code |= ERR_ALERT | ERR_FATAL;
6354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006356
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006359 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006365 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 }
6370 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006372 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006373 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
6377 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_ALERT | ERR_FATAL;
6382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 }
6384
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006386 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006387 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
6391 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006393 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006394 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 }
6398 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006400 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006401 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006406 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006407
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 if (curproxy == &defproxy) {
6409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006410 err_code |= ERR_ALERT | ERR_FATAL;
6411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006413 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006414 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 if (*(args[1]) == 0) {
6417 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006422 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006423 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6424 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6425 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006426 err_code |= ERR_ALERT | ERR_FATAL;
6427 goto out;
6428 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006429 err_code |= warnif_cond_conflicts(cond,
6430 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6431 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006432 }
6433 else if (*args[2]) {
6434 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6435 file, linenum, args[0], args[2]);
6436 err_code |= ERR_ALERT | ERR_FATAL;
6437 goto out;
6438 }
6439
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006440 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006441 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006442 wl->s = strdup(args[1]);
6443 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
6445 else if (!strcmp(args[0], "errorloc") ||
6446 !strcmp(args[0], "errorloc302") ||
6447 !strcmp(args[0], "errorloc303")) { /* error location */
6448 int errnum, errlen;
6449 char *err;
6450
Willy Tarreau977b8e42006-12-29 14:19:17 +01006451 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006452 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006453
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006455 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 }
6459
6460 errnum = atol(args[1]);
6461 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006462 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6463 err = malloc(errlen);
6464 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006465 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006466 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6467 err = malloc(errlen);
6468 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470
Willy Tarreau0f772532006-12-23 20:51:41 +01006471 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6472 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006473 chunk_destroy(&curproxy->errmsg[rc]);
6474 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006475 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006478
6479 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006480 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6481 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 free(err);
6483 }
6484 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006485 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6486 int errnum, errlen, fd;
6487 char *err;
6488 struct stat stat;
6489
6490 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006491 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006492
6493 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006494 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006495 err_code |= ERR_ALERT | ERR_FATAL;
6496 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006497 }
6498
6499 fd = open(args[2], O_RDONLY);
6500 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6501 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6502 file, linenum, args[2], args[1]);
6503 if (fd >= 0)
6504 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006505 err_code |= ERR_ALERT | ERR_FATAL;
6506 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006507 }
6508
Willy Tarreau27a674e2009-08-17 07:23:33 +02006509 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006510 errlen = stat.st_size;
6511 } else {
6512 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006513 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006514 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006515 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006516 }
6517
6518 err = malloc(errlen); /* malloc() must succeed during parsing */
6519 errnum = read(fd, err, errlen);
6520 if (errnum != errlen) {
6521 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6522 file, linenum, args[2], args[1]);
6523 close(fd);
6524 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006525 err_code |= ERR_ALERT | ERR_FATAL;
6526 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006527 }
6528 close(fd);
6529
6530 errnum = atol(args[1]);
6531 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6532 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006533 chunk_destroy(&curproxy->errmsg[rc]);
6534 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006535 break;
6536 }
6537 }
6538
6539 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006540 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6541 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006542 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006543 free(err);
6544 }
6545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006547 struct cfg_kw_list *kwl;
6548 int index;
6549
6550 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6551 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6552 if (kwl->kw[index].section != CFG_LISTEN)
6553 continue;
6554 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6555 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006556 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006557 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006558 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006559 err_code |= ERR_ALERT | ERR_FATAL;
6560 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006561 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006562 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006563 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006564 err_code |= ERR_WARN;
6565 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006566 }
Willy Tarreau93893792009-07-23 13:19:11 +02006567 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006568 }
6569 }
6570 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006571
Willy Tarreau6daf3432008-01-22 16:44:08 +01006572 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006573 err_code |= ERR_ALERT | ERR_FATAL;
6574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575 }
Willy Tarreau93893792009-07-23 13:19:11 +02006576 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006577 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006578 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579}
6580
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006581int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006582cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6583{
6584#ifdef CONFIG_HAP_NS
6585 const char *err;
6586 const char *item = args[0];
6587
6588 if (!strcmp(item, "namespace_list")) {
6589 return 0;
6590 }
6591 else if (!strcmp(item, "namespace")) {
6592 size_t idx = 1;
6593 const char *current;
6594 while (*(current = args[idx++])) {
6595 err = invalid_char(current);
6596 if (err) {
6597 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6598 file, linenum, *err, item, current);
6599 return ERR_ALERT | ERR_FATAL;
6600 }
6601
6602 if (netns_store_lookup(current, strlen(current))) {
6603 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6604 file, linenum, current);
6605 return ERR_ALERT | ERR_FATAL;
6606 }
6607 if (!netns_store_insert(current)) {
6608 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6609 file, linenum, current);
6610 return ERR_ALERT | ERR_FATAL;
6611 }
6612 }
6613 }
6614
6615 return 0;
6616#else
6617 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6618 file, linenum);
6619 return ERR_ALERT | ERR_FATAL;
6620#endif
6621}
6622
6623int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006624cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6625{
6626
6627 int err_code = 0;
6628 const char *err;
6629
6630 if (!strcmp(args[0], "userlist")) { /* new userlist */
6631 struct userlist *newul;
6632
6633 if (!*args[1]) {
6634 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6635 file, linenum, args[0]);
6636 err_code |= ERR_ALERT | ERR_FATAL;
6637 goto out;
6638 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6640 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006641
6642 err = invalid_char(args[1]);
6643 if (err) {
6644 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6645 file, linenum, *err, args[0], args[1]);
6646 err_code |= ERR_ALERT | ERR_FATAL;
6647 goto out;
6648 }
6649
6650 for (newul = userlist; newul; newul = newul->next)
6651 if (!strcmp(newul->name, args[1])) {
6652 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6653 file, linenum, args[1]);
6654 err_code |= ERR_WARN;
6655 goto out;
6656 }
6657
Vincent Bernat02779b62016-04-03 13:48:43 +02006658 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006659 if (!newul) {
6660 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6661 err_code |= ERR_ALERT | ERR_ABORT;
6662 goto out;
6663 }
6664
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006665 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006666 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006667 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6668 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006669 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006670 goto out;
6671 }
6672
6673 newul->next = userlist;
6674 userlist = newul;
6675
6676 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006677 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006678 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006679 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006680
6681 if (!*args[1]) {
6682 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6683 file, linenum, args[0]);
6684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
6686 }
6687
6688 err = invalid_char(args[1]);
6689 if (err) {
6690 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6691 file, linenum, *err, args[0], args[1]);
6692 err_code |= ERR_ALERT | ERR_FATAL;
6693 goto out;
6694 }
6695
William Lallemand4ac9f542015-05-28 18:03:51 +02006696 if (!userlist)
6697 goto out;
6698
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006699 for (ag = userlist->groups; ag; ag = ag->next)
6700 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006701 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6702 file, linenum, args[1], userlist->name);
6703 err_code |= ERR_ALERT;
6704 goto out;
6705 }
6706
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006707 ag = calloc(1, sizeof(*ag));
6708 if (!ag) {
6709 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6710 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006711 goto out;
6712 }
6713
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006714 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006715 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006716 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6717 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006718 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006719 goto out;
6720 }
6721
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 cur_arg = 2;
6723
6724 while (*args[cur_arg]) {
6725 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006726 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006727 cur_arg += 2;
6728 continue;
6729 } else {
6730 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6731 file, linenum, args[0]);
6732 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006733 free(ag->groupusers);
6734 free(ag->name);
6735 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006736 goto out;
6737 }
6738 }
6739
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006740 ag->next = userlist->groups;
6741 userlist->groups = ag;
6742
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006743 } else if (!strcmp(args[0], "user")) { /* new user */
6744 struct auth_users *newuser;
6745 int cur_arg;
6746
6747 if (!*args[1]) {
6748 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6749 file, linenum, args[0]);
6750 err_code |= ERR_ALERT | ERR_FATAL;
6751 goto out;
6752 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006753 if (!userlist)
6754 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006755
6756 for (newuser = userlist->users; newuser; newuser = newuser->next)
6757 if (!strcmp(newuser->user, args[1])) {
6758 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6759 file, linenum, args[1], userlist->name);
6760 err_code |= ERR_ALERT;
6761 goto out;
6762 }
6763
Vincent Bernat02779b62016-04-03 13:48:43 +02006764 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 if (!newuser) {
6766 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6767 err_code |= ERR_ALERT | ERR_ABORT;
6768 goto out;
6769 }
6770
6771 newuser->user = strdup(args[1]);
6772
6773 newuser->next = userlist->users;
6774 userlist->users = newuser;
6775
6776 cur_arg = 2;
6777
6778 while (*args[cur_arg]) {
6779 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006780#ifdef CONFIG_HAP_CRYPT
6781 if (!crypt("", args[cur_arg + 1])) {
6782 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6783 file, linenum, newuser->user);
6784 err_code |= ERR_ALERT | ERR_FATAL;
6785 goto out;
6786 }
6787#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006788 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6789 file, linenum);
6790 err_code |= ERR_ALERT;
6791#endif
6792 newuser->pass = strdup(args[cur_arg + 1]);
6793 cur_arg += 2;
6794 continue;
6795 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6796 newuser->pass = strdup(args[cur_arg + 1]);
6797 newuser->flags |= AU_O_INSECURE;
6798 cur_arg += 2;
6799 continue;
6800 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006801 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 cur_arg += 2;
6803 continue;
6804 } else {
6805 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6806 file, linenum, args[0]);
6807 err_code |= ERR_ALERT | ERR_FATAL;
6808 goto out;
6809 }
6810 }
6811 } else {
6812 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6813 err_code |= ERR_ALERT | ERR_FATAL;
6814 }
6815
6816out:
6817 return err_code;
6818}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006819
Christopher Faulet79bdef32016-11-04 22:36:15 +01006820int
6821cfg_parse_scope(const char *file, int linenum, char *line)
6822{
6823 char *beg, *end, *scope = NULL;
6824 int err_code = 0;
6825 const char *err;
6826
6827 beg = line + 1;
6828 end = strchr(beg, ']');
6829
6830 /* Detect end of scope declaration */
6831 if (!end || end == beg) {
6832 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6833 file, linenum);
6834 err_code |= ERR_ALERT | ERR_FATAL;
6835 goto out;
6836 }
6837
6838 /* Get scope name and check its validity */
6839 scope = my_strndup(beg, end-beg);
6840 err = invalid_char(scope);
6841 if (err) {
6842 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6843 file, linenum, *err);
6844 err_code |= ERR_ALERT | ERR_ABORT;
6845 goto out;
6846 }
6847
6848 /* Be sure to have a scope declaration alone on its line */
6849 line = end+1;
6850 while (isspace((unsigned char)*line))
6851 line++;
6852 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6853 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6854 file, linenum, *line);
6855 err_code |= ERR_ALERT | ERR_ABORT;
6856 goto out;
6857 }
6858
6859 /* We have a valid scope declaration, save it */
6860 free(cfg_scope);
6861 cfg_scope = scope;
6862 scope = NULL;
6863
6864 out:
6865 free(scope);
6866 return err_code;
6867}
6868
Willy Tarreaubaaee002006-06-26 02:48:02 +02006869/*
6870 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006871 * Returns the error code, 0 if OK, or any combination of :
6872 * - ERR_ABORT: must abort ASAP
6873 * - ERR_FATAL: we can continue parsing but not start the service
6874 * - ERR_WARN: a warning has been emitted
6875 * - ERR_ALERT: an alert has been emitted
6876 * Only the two first ones can stop processing, the two others are just
6877 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006879int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006880{
William Lallemand64e84512015-05-12 14:25:37 +02006881 char *thisline;
6882 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006883 FILE *f;
6884 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006885 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006886 struct cfg_section *cs = NULL;
6887 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006888 int readbytes = 0;
6889
6890 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006891 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006892 return -1;
6893 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006894
David Carlier97880bb2016-04-08 10:35:26 +01006895 if ((f=fopen(file,"r")) == NULL) {
6896 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006899
William Lallemandb2f07452015-05-12 14:27:13 +02006900next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006901 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006902 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006903 char *end;
6904 char *args[MAX_LINE_ARGS + 1];
6905 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006906 int dquote = 0; /* double quote */
6907 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006908
Willy Tarreaubaaee002006-06-26 02:48:02 +02006909 linenum++;
6910
6911 end = line + strlen(line);
6912
William Lallemand64e84512015-05-12 14:25:37 +02006913 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006914 /* Check if we reached the limit and the last char is not \n.
6915 * Watch out for the last line without the terminating '\n'!
6916 */
William Lallemand64e84512015-05-12 14:25:37 +02006917 char *newline;
6918 int newlinesize = linesize * 2;
6919
6920 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6921 if (newline == NULL) {
6922 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6923 file, linenum);
6924 err_code |= ERR_ALERT | ERR_FATAL;
6925 continue;
6926 }
6927
6928 readbytes = linesize - 1;
6929 linesize = newlinesize;
6930 thisline = newline;
6931 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006932 }
6933
William Lallemand64e84512015-05-12 14:25:37 +02006934 readbytes = 0;
6935
Willy Tarreaubaaee002006-06-26 02:48:02 +02006936 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006937 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006938 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006939
Christopher Faulet79bdef32016-11-04 22:36:15 +01006940
6941 if (*line == '[') {/* This is the begining if a scope */
6942 err_code |= cfg_parse_scope(file, linenum, line);
6943 goto next_line;
6944 }
6945
Willy Tarreaubaaee002006-06-26 02:48:02 +02006946 arg = 0;
6947 args[arg] = line;
6948
6949 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006950 if (*line == '"' && !squote) { /* double quote outside single quotes */
6951 if (dquote)
6952 dquote = 0;
6953 else
6954 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006955 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006956 end--;
6957 }
6958 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6959 if (squote)
6960 squote = 0;
6961 else
6962 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006963 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006964 end--;
6965 }
6966 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006967 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6968 * C equivalent value. Other combinations left unchanged (eg: \1).
6969 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970 int skip = 0;
6971 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6972 *line = line[1];
6973 skip = 1;
6974 }
6975 else if (line[1] == 'r') {
6976 *line = '\r';
6977 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979 else if (line[1] == 'n') {
6980 *line = '\n';
6981 skip = 1;
6982 }
6983 else if (line[1] == 't') {
6984 *line = '\t';
6985 skip = 1;
6986 }
6987 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006988 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006989 unsigned char hex1, hex2;
6990 hex1 = toupper(line[2]) - '0';
6991 hex2 = toupper(line[3]) - '0';
6992 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6993 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6994 *line = (hex1<<4) + hex2;
6995 skip = 3;
6996 }
6997 else {
6998 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006999 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007001 } else if (line[1] == '"') {
7002 *line = '"';
7003 skip = 1;
7004 } else if (line[1] == '\'') {
7005 *line = '\'';
7006 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007007 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7008 *line = '$';
7009 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 }
7011 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007012 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013 end -= skip;
7014 }
7015 line++;
7016 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007017 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 /* end of string, end of loop */
7019 *line = 0;
7020 break;
7021 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007022 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007023 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007024 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007025 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026 line++;
7027 args[++arg] = line;
7028 }
William Lallemandb2f07452015-05-12 14:27:13 +02007029 else if (dquote && *line == '$') {
7030 /* environment variables are evaluated inside double quotes */
7031 char *var_beg;
7032 char *var_end;
7033 char save_char;
7034 char *value;
7035 int val_len;
7036 int newlinesize;
7037 int braces = 0;
7038
7039 var_beg = line + 1;
7040 var_end = var_beg;
7041
7042 if (*var_beg == '{') {
7043 var_beg++;
7044 var_end++;
7045 braces = 1;
7046 }
7047
7048 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7049 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7050 err_code |= ERR_ALERT | ERR_FATAL;
7051 goto next_line; /* skip current line */
7052 }
7053
7054 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7055 var_end++;
7056
7057 save_char = *var_end;
7058 *var_end = '\0';
7059 value = getenv(var_beg);
7060 *var_end = save_char;
7061 val_len = value ? strlen(value) : 0;
7062
7063 if (braces) {
7064 if (*var_end == '}') {
7065 var_end++;
7066 braces = 0;
7067 } else {
7068 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7069 err_code |= ERR_ALERT | ERR_FATAL;
7070 goto next_line; /* skip current line */
7071 }
7072 }
7073
7074 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7075
7076 /* if not enough space in thisline */
7077 if (newlinesize > linesize) {
7078 char *newline;
7079
7080 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7081 if (newline == NULL) {
7082 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7083 err_code |= ERR_ALERT | ERR_FATAL;
7084 goto next_line; /* slip current line */
7085 }
7086 /* recompute pointers if realloc returns a new pointer */
7087 if (newline != thisline) {
7088 int i;
7089 int diff;
7090
7091 for (i = 0; i <= arg; i++) {
7092 diff = args[i] - thisline;
7093 args[i] = newline + diff;
7094 }
7095
7096 diff = var_end - thisline;
7097 var_end = newline + diff;
7098 diff = end - thisline;
7099 end = newline + diff;
7100 diff = line - thisline;
7101 line = newline + diff;
7102 thisline = newline;
7103 }
7104 linesize = newlinesize;
7105 }
7106
7107 /* insert value inside the line */
7108 memmove(line + val_len, var_end, end - var_end + 1);
7109 memcpy(line, value, val_len);
7110 end += val_len - (var_end - line);
7111 line += val_len;
7112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007113 else {
7114 line++;
7115 }
7116 }
William Lallemandb2f07452015-05-12 14:27:13 +02007117
William Lallemandf9873ba2015-05-05 17:37:14 +02007118 if (dquote) {
7119 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7120 err_code |= ERR_ALERT | ERR_FATAL;
7121 }
7122
7123 if (squote) {
7124 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7125 err_code |= ERR_ALERT | ERR_FATAL;
7126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007127
7128 /* empty line */
7129 if (!**args)
7130 continue;
7131
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007132 if (*line) {
7133 /* we had to stop due to too many args.
7134 * Let's terminate the string, print the offending part then cut the
7135 * last arg.
7136 */
7137 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7138 line++;
7139 *line = '\0';
7140
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007141 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007142 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007143 err_code |= ERR_ALERT | ERR_FATAL;
7144 args[arg] = line;
7145 }
7146
Willy Tarreau540abe42007-05-02 20:50:16 +02007147 /* zero out remaining args and ensure that at least one entry
7148 * is zeroed out.
7149 */
7150 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151 args[arg] = line;
7152 }
7153
Willy Tarreau3842f002009-06-14 11:39:52 +02007154 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007155 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007156 char *tmp;
7157
Willy Tarreau3842f002009-06-14 11:39:52 +02007158 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007159 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007160 for (arg=0; *args[arg+1]; arg++)
7161 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007162 *tmp = '\0'; // fix the next arg to \0
7163 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007164 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007165 else if (!strcmp(args[0], "default")) {
7166 kwm = KWM_DEF;
7167 for (arg=0; *args[arg+1]; arg++)
7168 args[arg] = args[arg+1]; // shift args after inversion
7169 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007170
William Lallemand0f99e342011-10-12 17:50:54 +02007171 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7172 strcmp(args[0], "log") != 0) {
7173 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007174 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007175 }
7176
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007177 /* detect section start */
7178 list_for_each_entry(ics, &sections, list) {
7179 if (strcmp(args[0], ics->section_name) == 0) {
7180 cursection = ics->section_name;
7181 cs = ics;
7182 break;
7183 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007184 }
7185
Willy Tarreaubaaee002006-06-26 02:48:02 +02007186 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007187 if (cs)
7188 err_code |= cs->section_parser(file, linenum, args, kwm);
7189 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007190 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007191 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007192 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007193
7194 if (err_code & ERR_ABORT)
7195 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007197 free(cfg_scope);
7198 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007199 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007200 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007201 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007202 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007203}
7204
Willy Tarreau64ab6072014-09-16 12:17:36 +02007205/* This function propagates processes from frontend <from> to backend <to> so
7206 * that it is always guaranteed that a backend pointed to by a frontend is
7207 * bound to all of its processes. After that, if the target is a "listen"
7208 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007209 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007210 * checked first to ensure that <to> is already bound to all processes of
7211 * <from>, there is no risk of looping and we ensure to follow the shortest
7212 * path to the destination.
7213 *
7214 * It is possible to set <to> to NULL for the first call so that the function
7215 * takes care of visiting the initial frontend in <from>.
7216 *
7217 * It is important to note that the function relies on the fact that all names
7218 * have already been resolved.
7219 */
7220void propagate_processes(struct proxy *from, struct proxy *to)
7221{
7222 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007223
7224 if (to) {
7225 /* check whether we need to go down */
7226 if (from->bind_proc &&
7227 (from->bind_proc & to->bind_proc) == from->bind_proc)
7228 return;
7229
7230 if (!from->bind_proc && !to->bind_proc)
7231 return;
7232
7233 to->bind_proc = from->bind_proc ?
7234 (to->bind_proc | from->bind_proc) : 0;
7235
7236 /* now propagate down */
7237 from = to;
7238 }
7239
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007240 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007241 return;
7242
Willy Tarreauf6b70012014-12-18 14:00:43 +01007243 if (from->state == PR_STSTOPPED)
7244 return;
7245
Willy Tarreau64ab6072014-09-16 12:17:36 +02007246 /* default_backend */
7247 if (from->defbe.be)
7248 propagate_processes(from, from->defbe.be);
7249
7250 /* use_backend */
7251 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007252 if (rule->dynamic)
7253 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007254 to = rule->be.backend;
7255 propagate_processes(from, to);
7256 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007257}
7258
Willy Tarreaubb925012009-07-23 13:36:36 +02007259/*
7260 * Returns the error code, 0 if OK, or any combination of :
7261 * - ERR_ABORT: must abort ASAP
7262 * - ERR_FATAL: we can continue parsing but not start the service
7263 * - ERR_WARN: a warning has been emitted
7264 * - ERR_ALERT: an alert has been emitted
7265 * Only the two first ones can stop processing, the two others are just
7266 * indicators.
7267 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007268int check_config_validity()
7269{
7270 int cfgerr = 0;
7271 struct proxy *curproxy = NULL;
7272 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007273 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007274 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007275 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007276 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007277
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007278 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279 /*
7280 * Now, check for the integrity of all that we have collected.
7281 */
7282
7283 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007284 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007285
Willy Tarreau193b8c62012-11-22 00:17:38 +01007286 if (!global.tune.max_http_hdr)
7287 global.tune.max_http_hdr = MAX_HTTP_HDR;
7288
7289 if (!global.tune.cookie_len)
7290 global.tune.cookie_len = CAPTURE_LEN;
7291
7292 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7293
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007294 /* Post initialisation of the users and groups lists. */
7295 err_code = userlist_postinit();
7296 if (err_code != ERR_NONE)
7297 goto out;
7298
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007299 /* first, we will invert the proxy list order */
7300 curproxy = NULL;
7301 while (proxy) {
7302 struct proxy *next;
7303
7304 next = proxy->next;
7305 proxy->next = curproxy;
7306 curproxy = proxy;
7307 if (!next)
7308 break;
7309 proxy = next;
7310 }
7311
Willy Tarreau419ead82014-09-16 13:41:21 +02007312 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007313 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007314 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007315 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007316 struct act_rule *trule;
7317 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007318 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007319 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007320 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007321
Willy Tarreau050536d2012-10-04 08:47:34 +02007322 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007323 /* proxy ID not set, use automatic numbering with first
7324 * spare entry starting with next_pxid.
7325 */
7326 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7327 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7328 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007329 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007330 next_pxid++;
7331
Willy Tarreau55ea7572007-06-17 19:56:27 +02007332
Willy Tarreaubaaee002006-06-26 02:48:02 +02007333 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007334 /* ensure we don't keep listeners uselessly bound */
7335 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007336 free((void *)curproxy->table.peers.name);
7337 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007338 continue;
7339 }
7340
Willy Tarreau102df612014-05-07 23:56:38 +02007341 /* Check multi-process mode compatibility for the current proxy */
7342
7343 if (curproxy->bind_proc) {
7344 /* an explicit bind-process was specified, let's check how many
7345 * processes remain.
7346 */
David Carliere6c39412015-07-02 07:00:17 +00007347 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007348
7349 curproxy->bind_proc &= nbits(global.nbproc);
7350 if (!curproxy->bind_proc && nbproc == 1) {
7351 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);
7352 curproxy->bind_proc = 1;
7353 }
7354 else if (!curproxy->bind_proc && nbproc > 1) {
7355 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);
7356 curproxy->bind_proc = 0;
7357 }
7358 }
7359
Willy Tarreau3d209582014-05-09 17:06:11 +02007360 /* check and reduce the bind-proc of each listener */
7361 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7362 unsigned long mask;
7363
7364 if (!bind_conf->bind_proc)
7365 continue;
7366
7367 mask = nbits(global.nbproc);
7368 if (curproxy->bind_proc)
7369 mask &= curproxy->bind_proc;
7370 /* mask cannot be null here thanks to the previous checks */
7371
David Carliere6c39412015-07-02 07:00:17 +00007372 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007373 bind_conf->bind_proc &= mask;
7374
7375 if (!bind_conf->bind_proc && nbproc == 1) {
7376 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",
7377 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7378 bind_conf->bind_proc = mask & ~(mask - 1);
7379 }
7380 else if (!bind_conf->bind_proc && nbproc > 1) {
7381 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",
7382 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7383 bind_conf->bind_proc = 0;
7384 }
7385 }
7386
Willy Tarreauff01a212009-03-15 13:46:16 +01007387 switch (curproxy->mode) {
7388 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007389 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007390 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007391 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7392 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007393 cfgerr++;
7394 }
7395
7396 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007397 Warning("config : servers will be ignored for %s '%s'.\n",
7398 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007399 break;
7400
7401 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007402 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007403 break;
7404
7405 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007406 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007407 break;
7408 }
7409
Willy Tarreauf3934b82015-08-11 11:36:45 +02007410 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7411 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7412 proxy_type_str(curproxy), curproxy->id);
7413 err_code |= ERR_WARN;
7414 }
7415
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007416 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007417 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007418 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007419 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7420 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007421 cfgerr++;
7422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007423#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007424 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007425 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7426 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007427 cfgerr++;
7428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007429#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007430 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007431 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7432 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007433 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007434 }
7435 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007436 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007437 /* If no LB algo is set in a backend, and we're not in
7438 * transparent mode, dispatch mode nor proxy mode, we
7439 * want to use balance roundrobin by default.
7440 */
7441 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7442 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007443 }
7444 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007445
Willy Tarreau1620ec32011-08-06 17:05:02 +02007446 if (curproxy->options & PR_O_DISPATCH)
7447 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7448 else if (curproxy->options & PR_O_HTTP_PROXY)
7449 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7450 else if (curproxy->options & PR_O_TRANSP)
7451 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007452
Willy Tarreau1620ec32011-08-06 17:05:02 +02007453 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7454 if (curproxy->options & PR_O_DISABLE404) {
7455 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7456 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7457 err_code |= ERR_WARN;
7458 curproxy->options &= ~PR_O_DISABLE404;
7459 }
7460 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7461 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7462 "send-state", proxy_type_str(curproxy), curproxy->id);
7463 err_code |= ERR_WARN;
7464 curproxy->options &= ~PR_O2_CHK_SNDST;
7465 }
Willy Tarreauef781042010-01-27 11:53:01 +01007466 }
7467
Simon Horman98637e52014-06-20 12:30:16 +09007468 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7469 if (!global.external_check) {
7470 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7471 curproxy->id, "option external-check");
7472 cfgerr++;
7473 }
7474 if (!curproxy->check_command) {
7475 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7476 curproxy->id, "option external-check");
7477 cfgerr++;
7478 }
7479 }
7480
Simon Horman64e34162015-02-06 11:11:57 +09007481 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007482 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7483 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007484 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7485 "'email-alert myhostname', or 'email-alert to' "
7486 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007487 "to be present).\n",
7488 proxy_type_str(curproxy), curproxy->id);
7489 err_code |= ERR_WARN;
7490 free_email_alert(curproxy);
7491 }
7492 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007493 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007494 }
7495
Simon Horman98637e52014-06-20 12:30:16 +09007496 if (curproxy->check_command) {
7497 int clear = 0;
7498 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7499 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7500 "external-check command", proxy_type_str(curproxy), curproxy->id);
7501 err_code |= ERR_WARN;
7502 clear = 1;
7503 }
7504 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007505 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007506 curproxy->id, "external-check command");
7507 cfgerr++;
7508 }
7509 if (clear) {
7510 free(curproxy->check_command);
7511 curproxy->check_command = NULL;
7512 }
7513 }
7514
7515 if (curproxy->check_path) {
7516 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7517 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7518 "external-check path", proxy_type_str(curproxy), curproxy->id);
7519 err_code |= ERR_WARN;
7520 free(curproxy->check_path);
7521 curproxy->check_path = NULL;
7522 }
7523 }
7524
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007525 /* if a default backend was specified, let's find it */
7526 if (curproxy->defbe.name) {
7527 struct proxy *target;
7528
Willy Tarreauafb39922015-05-26 12:04:09 +02007529 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007530 if (!target) {
7531 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7532 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007533 cfgerr++;
7534 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007535 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7536 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007537 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007538 } else if (target->mode != curproxy->mode &&
7539 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7540
7541 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7542 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7543 curproxy->conf.file, curproxy->conf.line,
7544 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7545 target->conf.file, target->conf.line);
7546 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007547 } else {
7548 free(curproxy->defbe.name);
7549 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007550
7551 /* Emit a warning if this proxy also has some servers */
7552 if (curproxy->srv) {
7553 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7554 curproxy->id);
7555 err_code |= ERR_WARN;
7556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007557 }
7558 }
7559
Willy Tarreau55ea7572007-06-17 19:56:27 +02007560 /* find the target proxy for 'use_backend' rules */
7561 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007562 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007563 struct logformat_node *node;
7564 char *pxname;
7565
7566 /* Try to parse the string as a log format expression. If the result
7567 * of the parsing is only one entry containing a simple string, then
7568 * it's a standard string corresponding to a static rule, thus the
7569 * parsing is cancelled and be.name is restored to be resolved.
7570 */
7571 pxname = rule->be.name;
7572 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007573 curproxy->conf.args.ctx = ARGC_UBK;
7574 curproxy->conf.args.file = rule->file;
7575 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007576 err = NULL;
7577 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7578 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7579 rule->file, rule->line, pxname, err);
7580 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007581 cfgerr++;
7582 continue;
7583 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007584 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7585
7586 if (!LIST_ISEMPTY(&rule->be.expr)) {
7587 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7588 rule->dynamic = 1;
7589 free(pxname);
7590 continue;
7591 }
7592 /* simple string: free the expression and fall back to static rule */
7593 free(node->arg);
7594 free(node);
7595 }
7596
7597 rule->dynamic = 0;
7598 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007599
Willy Tarreauafb39922015-05-26 12:04:09 +02007600 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007601 if (!target) {
7602 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7603 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007604 cfgerr++;
7605 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007606 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7607 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007608 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007609 } else if (target->mode != curproxy->mode &&
7610 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7611
7612 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7613 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7614 curproxy->conf.file, curproxy->conf.line,
7615 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7616 target->conf.file, target->conf.line);
7617 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007618 } else {
7619 free((void *)rule->be.name);
7620 rule->be.backend = target;
7621 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007622 }
7623
Willy Tarreau64ab6072014-09-16 12:17:36 +02007624 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007625 list_for_each_entry(srule, &curproxy->server_rules, list) {
7626 struct server *target = findserver(curproxy, srule->srv.name);
7627
7628 if (!target) {
7629 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7630 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7631 cfgerr++;
7632 continue;
7633 }
7634 free((void *)srule->srv.name);
7635 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007636 }
7637
Emeric Brunb982a3d2010-01-04 15:45:53 +01007638 /* find the target table for 'stick' rules */
7639 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7640 struct proxy *target;
7641
Emeric Brun1d33b292010-01-04 15:47:17 +01007642 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7643 if (mrule->flags & STK_IS_STORE)
7644 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7645
Emeric Brunb982a3d2010-01-04 15:45:53 +01007646 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007647 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007648 else
7649 target = curproxy;
7650
7651 if (!target) {
7652 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7653 curproxy->id, mrule->table.name);
7654 cfgerr++;
7655 }
7656 else if (target->table.size == 0) {
7657 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7658 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7659 cfgerr++;
7660 }
Willy Tarreau12785782012-04-27 21:37:17 +02007661 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7662 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007663 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7664 cfgerr++;
7665 }
7666 else {
7667 free((void *)mrule->table.name);
7668 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007669 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007670 }
7671 }
7672
7673 /* find the target table for 'store response' rules */
7674 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7675 struct proxy *target;
7676
Emeric Brun1d33b292010-01-04 15:47:17 +01007677 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7678
Emeric Brunb982a3d2010-01-04 15:45:53 +01007679 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007680 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007681 else
7682 target = curproxy;
7683
7684 if (!target) {
7685 Alert("Proxy '%s': unable to find store table '%s'.\n",
7686 curproxy->id, mrule->table.name);
7687 cfgerr++;
7688 }
7689 else if (target->table.size == 0) {
7690 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7691 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7692 cfgerr++;
7693 }
Willy Tarreau12785782012-04-27 21:37:17 +02007694 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7695 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007696 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7697 cfgerr++;
7698 }
7699 else {
7700 free((void *)mrule->table.name);
7701 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007702 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007703 }
7704 }
7705
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007706 /* find the target table for 'tcp-request' layer 4 rules */
7707 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7708 struct proxy *target;
7709
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007710 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007711 continue;
7712
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007713 if (trule->arg.trk_ctr.table.n)
7714 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007715 else
7716 target = curproxy;
7717
7718 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007719 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007720 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007721 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007722 cfgerr++;
7723 }
7724 else if (target->table.size == 0) {
7725 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007726 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007727 cfgerr++;
7728 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007729 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007730 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007731 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007732 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007733 cfgerr++;
7734 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007735 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007736 free(trule->arg.trk_ctr.table.n);
7737 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007738 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007739 * to pass a list of counters to track and allocate them right here using
7740 * stktable_alloc_data_type().
7741 */
7742 }
7743 }
7744
Willy Tarreau620408f2016-10-21 16:37:51 +02007745 /* find the target table for 'tcp-request' layer 5 rules */
7746 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7747 struct proxy *target;
7748
7749 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7750 continue;
7751
7752 if (trule->arg.trk_ctr.table.n)
7753 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7754 else
7755 target = curproxy;
7756
7757 if (!target) {
7758 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7759 curproxy->id, trule->arg.trk_ctr.table.n,
7760 tcp_trk_idx(trule->action));
7761 cfgerr++;
7762 }
7763 else if (target->table.size == 0) {
7764 Alert("Proxy '%s': table '%s' used but not configured.\n",
7765 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7766 cfgerr++;
7767 }
7768 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7769 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7770 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7771 tcp_trk_idx(trule->action));
7772 cfgerr++;
7773 }
7774 else {
7775 free(trule->arg.trk_ctr.table.n);
7776 trule->arg.trk_ctr.table.t = &target->table;
7777 /* Note: if we decide to enhance the track-sc syntax, we may be able
7778 * to pass a list of counters to track and allocate them right here using
7779 * stktable_alloc_data_type().
7780 */
7781 }
7782 }
7783
Willy Tarreaud1f96522010-08-03 19:34:32 +02007784 /* find the target table for 'tcp-request' layer 6 rules */
7785 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7786 struct proxy *target;
7787
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007788 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007789 continue;
7790
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007791 if (trule->arg.trk_ctr.table.n)
7792 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007793 else
7794 target = curproxy;
7795
7796 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007797 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007798 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007799 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007800 cfgerr++;
7801 }
7802 else if (target->table.size == 0) {
7803 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007804 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007805 cfgerr++;
7806 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007807 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007808 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007809 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007810 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007811 cfgerr++;
7812 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007813 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007814 free(trule->arg.trk_ctr.table.n);
7815 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007816 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007817 * to pass a list of counters to track and allocate them right here using
7818 * stktable_alloc_data_type().
7819 */
7820 }
7821 }
7822
Baptiste Assmanne9544932015-11-03 23:31:35 +01007823 /* parse http-request capture rules to ensure id really exists */
7824 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7825 if (hrqrule->action != ACT_CUSTOM ||
7826 hrqrule->action_ptr != http_action_req_capture_by_id)
7827 continue;
7828
7829 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7830 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7831 curproxy->id, hrqrule->arg.capid.idx);
7832 cfgerr++;
7833 }
7834 }
7835
7836 /* parse http-response capture rules to ensure id really exists */
7837 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7838 if (hrqrule->action != ACT_CUSTOM ||
7839 hrqrule->action_ptr != http_action_res_capture_by_id)
7840 continue;
7841
7842 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7843 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7844 curproxy->id, hrqrule->arg.capid.idx);
7845 cfgerr++;
7846 }
7847 }
7848
Willy Tarreau09448f72014-06-25 18:12:15 +02007849 /* find the target table for 'http-request' layer 7 rules */
7850 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7851 struct proxy *target;
7852
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007853 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007854 continue;
7855
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007856 if (hrqrule->arg.trk_ctr.table.n)
7857 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007858 else
7859 target = curproxy;
7860
7861 if (!target) {
7862 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007863 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007864 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007865 cfgerr++;
7866 }
7867 else if (target->table.size == 0) {
7868 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007869 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007870 cfgerr++;
7871 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007872 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007873 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007874 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007875 http_trk_idx(hrqrule->action));
7876 cfgerr++;
7877 }
7878 else {
7879 free(hrqrule->arg.trk_ctr.table.n);
7880 hrqrule->arg.trk_ctr.table.t = &target->table;
7881 /* Note: if we decide to enhance the track-sc syntax, we may be able
7882 * to pass a list of counters to track and allocate them right here using
7883 * stktable_alloc_data_type().
7884 */
7885 }
7886 }
7887
7888 /* find the target table for 'http-response' layer 7 rules */
7889 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7890 struct proxy *target;
7891
7892 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7893 continue;
7894
7895 if (hrqrule->arg.trk_ctr.table.n)
7896 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7897 else
7898 target = curproxy;
7899
7900 if (!target) {
7901 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7902 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7903 http_trk_idx(hrqrule->action));
7904 cfgerr++;
7905 }
7906 else if (target->table.size == 0) {
7907 Alert("Proxy '%s': table '%s' used but not configured.\n",
7908 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7909 cfgerr++;
7910 }
7911 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
7912 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7913 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
7914 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007915 cfgerr++;
7916 }
7917 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007918 free(hrqrule->arg.trk_ctr.table.n);
7919 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007920 /* Note: if we decide to enhance the track-sc syntax, we may be able
7921 * to pass a list of counters to track and allocate them right here using
7922 * stktable_alloc_data_type().
7923 */
7924 }
7925 }
7926
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007927 /* move any "block" rules at the beginning of the http-request rules */
7928 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7929 /* insert block_rules into http_req_rules at the beginning */
7930 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7931 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7932 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7933 curproxy->http_req_rules.n = curproxy->block_rules.n;
7934 LIST_INIT(&curproxy->block_rules);
7935 }
7936
Emeric Brun32da3c42010-09-23 18:39:19 +02007937 if (curproxy->table.peers.name) {
7938 struct peers *curpeers = peers;
7939
7940 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7941 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7942 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007943 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007944 break;
7945 }
7946 }
7947
7948 if (!curpeers) {
7949 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7950 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007951 free((void *)curproxy->table.peers.name);
7952 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007953 cfgerr++;
7954 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007955 else if (curpeers->state == PR_STSTOPPED) {
7956 /* silently disable this peers section */
7957 curproxy->table.peers.p = NULL;
7958 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007959 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007960 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7961 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007962 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007963 cfgerr++;
7964 }
7965 }
7966
Simon Horman9dc49962015-01-30 11:22:59 +09007967
7968 if (curproxy->email_alert.mailers.name) {
7969 struct mailers *curmailers = mailers;
7970
7971 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7972 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7973 free(curproxy->email_alert.mailers.name);
7974 curproxy->email_alert.mailers.m = curmailers;
7975 curmailers->users++;
7976 break;
7977 }
7978 }
7979
7980 if (!curmailers) {
7981 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7982 curproxy->id, curproxy->email_alert.mailers.name);
7983 free_email_alert(curproxy);
7984 cfgerr++;
7985 }
7986 }
7987
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007988 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007989 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007990 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7991 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7992 "proxy", curproxy->id);
7993 cfgerr++;
7994 goto out_uri_auth_compat;
7995 }
7996
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007997 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007998 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007999 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008000 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008001
Willy Tarreau95fa4692010-02-01 13:05:50 +01008002 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8003 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008004
8005 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008006 uri_auth_compat_req[i++] = "realm";
8007 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8008 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008009
Willy Tarreau95fa4692010-02-01 13:05:50 +01008010 uri_auth_compat_req[i++] = "unless";
8011 uri_auth_compat_req[i++] = "{";
8012 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8013 uri_auth_compat_req[i++] = "}";
8014 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008015
Willy Tarreauff011f22011-01-06 17:51:27 +01008016 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8017 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008018 cfgerr++;
8019 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008020 }
8021
Willy Tarreauff011f22011-01-06 17:51:27 +01008022 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008023
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008024 if (curproxy->uri_auth->auth_realm) {
8025 free(curproxy->uri_auth->auth_realm);
8026 curproxy->uri_auth->auth_realm = NULL;
8027 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008028
8029 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008030 }
8031out_uri_auth_compat:
8032
Dragan Dosen43885c72015-10-01 13:18:13 +02008033 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008034 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008035 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8036 if (!curproxy->conf.logformat_sd_string) {
8037 /* set the default logformat_sd_string */
8038 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8039 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008040 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008041 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008042 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008043
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008044 /* compile the log format */
8045 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008046 if (curproxy->conf.logformat_string != default_http_log_format &&
8047 curproxy->conf.logformat_string != default_tcp_log_format &&
8048 curproxy->conf.logformat_string != clf_http_log_format)
8049 free(curproxy->conf.logformat_string);
8050 curproxy->conf.logformat_string = NULL;
8051 free(curproxy->conf.lfs_file);
8052 curproxy->conf.lfs_file = NULL;
8053 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008054
8055 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8056 free(curproxy->conf.logformat_sd_string);
8057 curproxy->conf.logformat_sd_string = NULL;
8058 free(curproxy->conf.lfsd_file);
8059 curproxy->conf.lfsd_file = NULL;
8060 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008061 }
8062
Willy Tarreau62a61232013-04-12 18:13:46 +02008063 if (curproxy->conf.logformat_string) {
8064 curproxy->conf.args.ctx = ARGC_LOG;
8065 curproxy->conf.args.file = curproxy->conf.lfs_file;
8066 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008067 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008068 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008069 SMP_VAL_FE_LOG_END, &err)) {
8070 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8071 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8072 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008073 cfgerr++;
8074 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008075 curproxy->conf.args.file = NULL;
8076 curproxy->conf.args.line = 0;
8077 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008078
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008079 if (curproxy->conf.logformat_sd_string) {
8080 curproxy->conf.args.ctx = ARGC_LOGSD;
8081 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8082 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008083 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008084 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 +01008085 SMP_VAL_FE_LOG_END, &err)) {
8086 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8087 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8088 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008089 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008090 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8091 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8092 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8093 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008094 cfgerr++;
8095 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008096 curproxy->conf.args.file = NULL;
8097 curproxy->conf.args.line = 0;
8098 }
8099
Willy Tarreau62a61232013-04-12 18:13:46 +02008100 if (curproxy->conf.uniqueid_format_string) {
8101 curproxy->conf.args.ctx = ARGC_UIF;
8102 curproxy->conf.args.file = curproxy->conf.uif_file;
8103 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008104 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008105 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 +01008106 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8107 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8108 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8109 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008110 cfgerr++;
8111 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008112 curproxy->conf.args.file = NULL;
8113 curproxy->conf.args.line = 0;
8114 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008115
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008116 /* only now we can check if some args remain unresolved.
8117 * This must be done after the users and groups resolution.
8118 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008119 cfgerr += smp_resolve_args(curproxy);
8120 if (!cfgerr)
8121 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008122
Willy Tarreau2738a142006-07-08 17:28:09 +02008123 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008124 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008125 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008126 (!curproxy->timeout.connect ||
8127 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008128 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008129 " | While not properly invalid, you will certainly encounter various problems\n"
8130 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008131 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008132 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008133 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008134 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008135
Willy Tarreau1fa31262007-12-03 00:36:16 +01008136 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8137 * We must still support older configurations, so let's find out whether those
8138 * parameters have been set or must be copied from contimeouts.
8139 */
8140 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008141 if (!curproxy->timeout.tarpit ||
8142 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008143 /* tarpit timeout not set. We search in the following order:
8144 * default.tarpit, curr.connect, default.connect.
8145 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008146 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008147 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008148 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008149 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008150 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008151 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008152 }
8153 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008154 (!curproxy->timeout.queue ||
8155 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008156 /* queue timeout not set. We search in the following order:
8157 * default.queue, curr.connect, default.connect.
8158 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008159 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008160 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008161 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008162 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008163 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008164 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008165 }
8166 }
8167
Willy Tarreau1620ec32011-08-06 17:05:02 +02008168 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008169 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008170 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008171 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008172 }
8173
Willy Tarreau215663d2014-06-13 18:30:23 +02008174 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8175 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8176 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8177 proxy_type_str(curproxy), curproxy->id);
8178 err_code |= ERR_WARN;
8179 }
8180
Willy Tarreau193b8c62012-11-22 00:17:38 +01008181 /* ensure that cookie capture length is not too large */
8182 if (curproxy->capture_len >= global.tune.cookie_len) {
8183 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8184 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8185 err_code |= ERR_WARN;
8186 curproxy->capture_len = global.tune.cookie_len - 1;
8187 }
8188
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008189 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008190 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008191 curproxy->req_cap_pool = create_pool("ptrcap",
8192 curproxy->nb_req_cap * sizeof(char *),
8193 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008194 }
8195
8196 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008197 curproxy->rsp_cap_pool = create_pool("ptrcap",
8198 curproxy->nb_rsp_cap * sizeof(char *),
8199 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008200 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008201
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008202 switch (curproxy->load_server_state_from_file) {
8203 case PR_SRV_STATE_FILE_UNSPEC:
8204 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8205 break;
8206 case PR_SRV_STATE_FILE_GLOBAL:
8207 if (!global.server_state_file) {
8208 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",
8209 curproxy->id);
8210 err_code |= ERR_WARN;
8211 }
8212 break;
8213 }
8214
Willy Tarreaubaaee002006-06-26 02:48:02 +02008215 /* first, we will invert the servers list order */
8216 newsrv = NULL;
8217 while (curproxy->srv) {
8218 struct server *next;
8219
8220 next = curproxy->srv->next;
8221 curproxy->srv->next = newsrv;
8222 newsrv = curproxy->srv;
8223 if (!next)
8224 break;
8225 curproxy->srv = next;
8226 }
8227
Willy Tarreau17edc812014-01-03 12:14:34 +01008228 /* Check that no server name conflicts. This causes trouble in the stats.
8229 * We only emit a warning for the first conflict affecting each server,
8230 * in order to avoid combinatory explosion if all servers have the same
8231 * name. We do that only for servers which do not have an explicit ID,
8232 * because these IDs were made also for distinguishing them and we don't
8233 * want to annoy people who correctly manage them.
8234 */
8235 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8236 struct server *other_srv;
8237
8238 if (newsrv->puid)
8239 continue;
8240
8241 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8242 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8243 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8244 newsrv->conf.file, newsrv->conf.line,
8245 proxy_type_str(curproxy), curproxy->id,
8246 newsrv->id, other_srv->conf.line);
8247 break;
8248 }
8249 }
8250 }
8251
Willy Tarreaudd701652010-05-25 23:03:02 +02008252 /* assign automatic UIDs to servers which don't have one yet */
8253 next_id = 1;
8254 newsrv = curproxy->srv;
8255 while (newsrv != NULL) {
8256 if (!newsrv->puid) {
8257 /* server ID not set, use automatic numbering with first
8258 * spare entry starting with next_svid.
8259 */
8260 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8261 newsrv->conf.id.key = newsrv->puid = next_id;
8262 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8263 }
8264 next_id++;
8265 newsrv = newsrv->next;
8266 }
8267
Willy Tarreau20697042007-11-15 23:26:18 +01008268 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008269 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008270
Willy Tarreau62c3be22012-01-20 13:12:32 +01008271 /*
8272 * If this server supports a maxconn parameter, it needs a dedicated
8273 * tasks to fill the emptied slots when a connection leaves.
8274 * Also, resolve deferred tracking dependency if needed.
8275 */
8276 newsrv = curproxy->srv;
8277 while (newsrv != NULL) {
8278 if (newsrv->minconn > newsrv->maxconn) {
8279 /* Only 'minconn' was specified, or it was higher than or equal
8280 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8281 * this will avoid further useless expensive computations.
8282 */
8283 newsrv->maxconn = newsrv->minconn;
8284 } else if (newsrv->maxconn && !newsrv->minconn) {
8285 /* minconn was not specified, so we set it to maxconn */
8286 newsrv->minconn = newsrv->maxconn;
8287 }
8288
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008289#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008290 if (newsrv->use_ssl || newsrv->check.use_ssl)
Willy Tarreau03209342016-12-22 17:08:28 +01008291 cfgerr += ssl_sock_prepare_srv_ctx(newsrv);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008292#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008293
Willy Tarreau2f075e92013-12-03 11:11:34 +01008294 /* set the check type on the server */
8295 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8296
Willy Tarreau62c3be22012-01-20 13:12:32 +01008297 if (newsrv->trackit) {
8298 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008299 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008300 char *pname, *sname;
8301
8302 pname = newsrv->trackit;
8303 sname = strrchr(pname, '/');
8304
8305 if (sname)
8306 *sname++ = '\0';
8307 else {
8308 sname = pname;
8309 pname = NULL;
8310 }
8311
8312 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008313 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008314 if (!px) {
8315 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8316 proxy_type_str(curproxy), curproxy->id,
8317 newsrv->id, pname);
8318 cfgerr++;
8319 goto next_srv;
8320 }
8321 } else
8322 px = curproxy;
8323
8324 srv = findserver(px, sname);
8325 if (!srv) {
8326 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8327 proxy_type_str(curproxy), curproxy->id,
8328 newsrv->id, sname);
8329 cfgerr++;
8330 goto next_srv;
8331 }
8332
Willy Tarreau32091232014-05-16 13:52:00 +02008333 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8334 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8335 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008336 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008337 "tracking as it does not have any check nor agent enabled.\n",
8338 proxy_type_str(curproxy), curproxy->id,
8339 newsrv->id, px->id, srv->id);
8340 cfgerr++;
8341 goto next_srv;
8342 }
8343
8344 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8345
8346 if (loop) {
8347 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8348 "belongs to a tracking chain looping back to %s/%s.\n",
8349 proxy_type_str(curproxy), curproxy->id,
8350 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008351 cfgerr++;
8352 goto next_srv;
8353 }
8354
8355 if (curproxy != px &&
8356 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8357 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8358 "tracking: disable-on-404 option inconsistency.\n",
8359 proxy_type_str(curproxy), curproxy->id,
8360 newsrv->id, px->id, srv->id);
8361 cfgerr++;
8362 goto next_srv;
8363 }
8364
Willy Tarreau62c3be22012-01-20 13:12:32 +01008365 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008366 newsrv->tracknext = srv->trackers;
8367 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008368
8369 free(newsrv->trackit);
8370 newsrv->trackit = NULL;
8371 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008372
8373 /*
8374 * resolve server's resolvers name and update the resolvers pointer
8375 * accordingly
8376 */
8377 if (newsrv->resolvers_id) {
8378 struct dns_resolvers *curr_resolvers;
8379 int found;
8380
8381 found = 0;
8382 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8383 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8384 found = 1;
8385 break;
8386 }
8387 }
8388
8389 if (!found) {
8390 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8391 proxy_type_str(curproxy), curproxy->id,
8392 newsrv->id, newsrv->resolvers_id);
8393 cfgerr++;
8394 } else {
8395 free(newsrv->resolvers_id);
8396 newsrv->resolvers_id = NULL;
8397 if (newsrv->resolution)
8398 newsrv->resolution->resolvers = curr_resolvers;
8399 }
8400 }
8401 else {
8402 /* if no resolvers section associated to this server
8403 * we can clean up the associated resolution structure
8404 */
8405 if (newsrv->resolution) {
8406 free(newsrv->resolution->hostname_dn);
8407 newsrv->resolution->hostname_dn = NULL;
8408 free(newsrv->resolution);
8409 newsrv->resolution = NULL;
8410 }
8411 }
8412
Willy Tarreau62c3be22012-01-20 13:12:32 +01008413 next_srv:
8414 newsrv = newsrv->next;
8415 }
8416
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008417 /* We have to initialize the server lookup mechanism depending
8418 * on what LB algorithm was choosen.
8419 */
8420
8421 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8422 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8423 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008424 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8425 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8426 init_server_map(curproxy);
8427 } else {
8428 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8429 fwrr_init_server_groups(curproxy);
8430 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008431 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008432
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008433 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008434 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8435 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8436 fwlc_init_server_tree(curproxy);
8437 } else {
8438 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8439 fas_init_server_tree(curproxy);
8440 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008441 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008442
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008443 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008444 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8445 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8446 chash_init_server_tree(curproxy);
8447 } else {
8448 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8449 init_server_map(curproxy);
8450 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008451 break;
8452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008453
8454 if (curproxy->options & PR_O_LOGASAP)
8455 curproxy->to_log &= ~LW_BYTES;
8456
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008457 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008458 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8459 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008460 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8461 proxy_type_str(curproxy), curproxy->id);
8462 err_code |= ERR_WARN;
8463 }
8464
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008465 if (curproxy->mode != PR_MODE_HTTP) {
8466 int optnum;
8467
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008468 if (curproxy->uri_auth) {
8469 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8470 proxy_type_str(curproxy), curproxy->id);
8471 err_code |= ERR_WARN;
8472 curproxy->uri_auth = NULL;
8473 }
8474
Willy Tarreau87cf5142011-08-19 22:57:24 +02008475 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008476 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8477 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8478 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008479 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008480 }
8481
8482 if (curproxy->options & PR_O_ORGTO) {
8483 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8484 "originalto", proxy_type_str(curproxy), curproxy->id);
8485 err_code |= ERR_WARN;
8486 curproxy->options &= ~PR_O_ORGTO;
8487 }
8488
8489 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8490 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8491 (curproxy->cap & cfg_opts[optnum].cap) &&
8492 (curproxy->options & cfg_opts[optnum].val)) {
8493 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8494 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8495 err_code |= ERR_WARN;
8496 curproxy->options &= ~cfg_opts[optnum].val;
8497 }
8498 }
8499
8500 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8501 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8502 (curproxy->cap & cfg_opts2[optnum].cap) &&
8503 (curproxy->options2 & cfg_opts2[optnum].val)) {
8504 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8505 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8506 err_code |= ERR_WARN;
8507 curproxy->options2 &= ~cfg_opts2[optnum].val;
8508 }
8509 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008510
Willy Tarreau29fbe512015-08-20 19:35:14 +02008511#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008512 if (curproxy->conn_src.bind_hdr_occ) {
8513 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008514 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008515 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008516 err_code |= ERR_WARN;
8517 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008518#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008519 }
8520
Willy Tarreaubaaee002006-06-26 02:48:02 +02008521 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008522 * ensure that we're not cross-dressing a TCP server into HTTP.
8523 */
8524 newsrv = curproxy->srv;
8525 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008526 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008527 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8528 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008529 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008530 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008531
Willy Tarreau0cec3312011-10-31 13:49:26 +01008532 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8533 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8534 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8535 err_code |= ERR_WARN;
8536 }
8537
Willy Tarreauc93cd162014-05-13 15:54:22 +02008538 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008539 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8540 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8541 err_code |= ERR_WARN;
8542 }
8543
Willy Tarreau29fbe512015-08-20 19:35:14 +02008544#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008545 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8546 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008547 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 +01008548 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008549 err_code |= ERR_WARN;
8550 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008551#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008552 newsrv = newsrv->next;
8553 }
8554
Willy Tarreaue42bd962014-09-16 16:21:19 +02008555 /* check if we have a frontend with "tcp-request content" looking at L7
8556 * with no inspect-delay
8557 */
8558 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8559 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008560 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008561 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008562 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008563 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008564 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008565 break;
8566 }
8567
8568 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8569 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8570 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8571 " This means that these rules will randomly find their contents. This can be fixed by"
8572 " setting the tcp-request inspect-delay.\n",
8573 proxy_type_str(curproxy), curproxy->id);
8574 err_code |= ERR_WARN;
8575 }
8576 }
8577
Christopher Fauletd7c91962015-04-30 11:48:27 +02008578 /* Check filter configuration, if any */
8579 cfgerr += flt_check(curproxy);
8580
Willy Tarreauc1a21672009-08-16 22:37:44 +02008581 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008582 if (!curproxy->accept)
8583 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008584
Willy Tarreauc1a21672009-08-16 22:37:44 +02008585 if (curproxy->tcp_req.inspect_delay ||
8586 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008587 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008588
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008589 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008590 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008591 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008592 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008593
8594 /* both TCP and HTTP must check switching rules */
8595 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008596
8597 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008598 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008599 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8600 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008601 if (curproxy->mode == PR_MODE_HTTP) {
8602 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8603 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8604 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008605 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008606 }
8607
8608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008609 if (curproxy->tcp_req.inspect_delay ||
8610 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8611 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8612
Emeric Brun97679e72010-09-23 17:56:44 +02008613 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8614 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8615
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008616 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008617 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008618 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008619 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008620
8621 /* If the backend does requires RDP cookie persistence, we have to
8622 * enable the corresponding analyser.
8623 */
8624 if (curproxy->options2 & PR_O2_RDPC_PRST)
8625 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008626
8627 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008628 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008629 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8630 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008631 if (curproxy->mode == PR_MODE_HTTP) {
8632 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8633 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8634 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008635 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008636 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008637 }
8638
8639 /***********************************************************/
8640 /* At this point, target names have already been resolved. */
8641 /***********************************************************/
8642
8643 /* Check multi-process mode compatibility */
8644
8645 if (global.nbproc > 1 && global.stats_fe) {
8646 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8647 unsigned long mask;
8648
8649 mask = nbits(global.nbproc);
8650 if (global.stats_fe->bind_proc)
8651 mask &= global.stats_fe->bind_proc;
8652
8653 if (bind_conf->bind_proc)
8654 mask &= bind_conf->bind_proc;
8655
8656 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008657 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008658 break;
8659 }
8660 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8661 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");
8662 }
8663 }
8664
8665 /* Make each frontend inherit bind-process from its listeners when not specified. */
8666 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8667 if (curproxy->bind_proc)
8668 continue;
8669
8670 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8671 unsigned long mask;
8672
Willy Tarreaue428b082015-05-04 21:57:58 +02008673 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008674 curproxy->bind_proc |= mask;
8675 }
8676
8677 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008678 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008679 }
8680
8681 if (global.stats_fe) {
8682 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8683 unsigned long mask;
8684
Cyril Bonté06181952016-02-24 00:14:54 +01008685 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008686 global.stats_fe->bind_proc |= mask;
8687 }
8688 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008689 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008690 }
8691
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008692 /* propagate bindings from frontends to backends. Don't do it if there
8693 * are any fatal errors as we must not call it with unresolved proxies.
8694 */
8695 if (!cfgerr) {
8696 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8697 if (curproxy->cap & PR_CAP_FE)
8698 propagate_processes(curproxy, NULL);
8699 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008700 }
8701
8702 /* Bind each unbound backend to all processes when not specified. */
8703 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8704 if (curproxy->bind_proc)
8705 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008706 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008707 }
8708
8709 /*******************************************************/
8710 /* At this step, all proxies have a non-null bind_proc */
8711 /*******************************************************/
8712
8713 /* perform the final checks before creating tasks */
8714
8715 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8716 struct listener *listener;
8717 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008718
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008719 /* Configure SSL for each bind line.
8720 * Note: if configuration fails at some point, the ->ctx member
8721 * remains NULL so that listeners can later detach.
8722 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008723 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008724 if (bind_conf->xprt->prepare_bind_conf &&
8725 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008726 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008727 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008728
Willy Tarreaue6b98942007-10-29 01:09:36 +01008729 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008730 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008731 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008732 int nbproc;
8733
8734 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008735 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008736 nbits(global.nbproc));
8737
8738 if (!nbproc) /* no intersection between listener and frontend */
8739 nbproc = 1;
8740
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008741 if (!listener->luid) {
8742 /* listener ID not set, use automatic numbering with first
8743 * spare entry starting with next_luid.
8744 */
8745 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8746 listener->conf.id.key = listener->luid = next_id;
8747 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008748 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008749 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008750
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008751 /* enable separate counters */
8752 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008753 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008754 if (!listener->name)
8755 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008756 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008757
Willy Tarreaue6b98942007-10-29 01:09:36 +01008758 if (curproxy->options & PR_O_TCP_NOLING)
8759 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008760 if (!listener->maxconn)
8761 listener->maxconn = curproxy->maxconn;
8762 if (!listener->backlog)
8763 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008764 if (!listener->maxaccept)
8765 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8766
8767 /* we want to have an optimal behaviour on single process mode to
8768 * maximize the work at once, but in multi-process we want to keep
8769 * some fairness between processes, so we target half of the max
8770 * number of events to be balanced over all the processes the proxy
8771 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8772 * used to disable the limit.
8773 */
8774 if (listener->maxaccept > 0) {
8775 if (nbproc > 1)
8776 listener->maxaccept = (listener->maxaccept + 1) / 2;
8777 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8778 }
8779
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008780 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008781 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008782 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008783 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008784
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008785 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008786 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008787
Willy Tarreau620408f2016-10-21 16:37:51 +02008788 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8789 listener->options |= LI_O_TCP_L5_RULES;
8790
Willy Tarreaude3041d2010-05-31 10:56:17 +02008791 if (curproxy->mon_mask.s_addr)
8792 listener->options |= LI_O_CHK_MONNET;
8793
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008794 /* smart accept mode is automatic in HTTP mode */
8795 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008796 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008797 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8798 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008799 }
8800
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008801 /* Release unused SSL configs */
8802 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008803 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8804 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008805 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008806
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008807 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008808 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008809 int count, maxproc = 0;
8810
8811 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008812 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008813 if (count > maxproc)
8814 maxproc = count;
8815 }
8816 /* backends have 0, frontends have 1 or more */
8817 if (maxproc != 1)
8818 Warning("Proxy '%s': in multi-process mode, stats will be"
8819 " limited to process assigned to the current request.\n",
8820 curproxy->id);
8821
Willy Tarreau102df612014-05-07 23:56:38 +02008822 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8823 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8824 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008825 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008826 }
Willy Tarreau102df612014-05-07 23:56:38 +02008827 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8828 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8829 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008830 }
8831 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008832
8833 /* create the task associated with the proxy */
8834 curproxy->task = task_new();
8835 if (curproxy->task) {
8836 curproxy->task->context = curproxy;
8837 curproxy->task->process = manage_proxy;
8838 /* no need to queue, it will be done automatically if some
8839 * listener gets limited.
8840 */
8841 curproxy->task->expire = TICK_ETERNITY;
8842 } else {
8843 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8844 curproxy->id);
8845 cfgerr++;
8846 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008847 }
8848
Willy Tarreaufbb78422011-06-05 15:38:35 +02008849 /* automatically compute fullconn if not set. We must not do it in the
8850 * loop above because cross-references are not yet fully resolved.
8851 */
8852 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8853 /* If <fullconn> is not set, let's set it to 10% of the sum of
8854 * the possible incoming frontend's maxconns.
8855 */
8856 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8857 struct proxy *fe;
8858 int total = 0;
8859
8860 /* sum up the number of maxconns of frontends which
8861 * reference this backend at least once or which are
8862 * the same one ('listen').
8863 */
8864 for (fe = proxy; fe; fe = fe->next) {
8865 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008866 int found = 0;
8867
8868 if (!(fe->cap & PR_CAP_FE))
8869 continue;
8870
8871 if (fe == curproxy) /* we're on a "listen" instance */
8872 found = 1;
8873
8874 if (fe->defbe.be == curproxy) /* "default_backend" */
8875 found = 1;
8876
8877 /* check if a "use_backend" rule matches */
8878 if (!found) {
8879 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008880 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008881 found = 1;
8882 break;
8883 }
8884 }
8885 }
8886
Willy Tarreaufbb78422011-06-05 15:38:35 +02008887 /* now we've checked all possible ways to reference a backend
8888 * from a frontend.
8889 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008890 if (!found)
8891 continue;
8892 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008893 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008894 /* we have the sum of the maxconns in <total>. We only
8895 * keep 10% of that sum to set the default fullconn, with
8896 * a hard minimum of 1 (to avoid a divide by zero).
8897 */
8898 curproxy->fullconn = (total + 9) / 10;
8899 if (!curproxy->fullconn)
8900 curproxy->fullconn = 1;
8901 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008902 }
8903
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008904 /*
8905 * Recount currently required checks.
8906 */
8907
8908 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8909 int optnum;
8910
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008911 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8912 if (curproxy->options & cfg_opts[optnum].val)
8913 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008914
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008915 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8916 if (curproxy->options2 & cfg_opts2[optnum].val)
8917 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008918 }
8919
Willy Tarreau0fca4832015-05-01 19:12:05 +02008920 /* compute the required process bindings for the peers */
8921 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8922 if (curproxy->table.peers.p)
8923 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8924
Willy Tarreau122541c2011-09-07 21:24:49 +02008925 if (peers) {
8926 struct peers *curpeers = peers, **last;
8927 struct peer *p, *pb;
8928
Willy Tarreau1e273012015-05-01 19:15:17 +02008929 /* Remove all peers sections which don't have a valid listener,
8930 * which are not used by any table, or which are bound to more
8931 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008932 */
8933 last = &peers;
8934 while (*last) {
8935 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008936
8937 if (curpeers->state == PR_STSTOPPED) {
8938 /* the "disabled" keyword was present */
8939 if (curpeers->peers_fe)
8940 stop_proxy(curpeers->peers_fe);
8941 curpeers->peers_fe = NULL;
8942 }
8943 else if (!curpeers->peers_fe) {
8944 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8945 curpeers->id, localpeer);
8946 }
David Carliere6c39412015-07-02 07:00:17 +00008947 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008948 /* either it's totally stopped or too much used */
8949 if (curpeers->peers_fe->bind_proc) {
8950 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008951 "running in different processes (%d different ones). "
8952 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008953 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008954 cfgerr++;
8955 }
8956 stop_proxy(curpeers->peers_fe);
8957 curpeers->peers_fe = NULL;
8958 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008959 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008960 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008961 last = &curpeers->next;
8962 continue;
8963 }
8964
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008965 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008966 p = curpeers->remote;
8967 while (p) {
8968 pb = p->next;
8969 free(p->id);
8970 free(p);
8971 p = pb;
8972 }
8973
8974 /* Destroy and unlink this curpeers section.
8975 * Note: curpeers is backed up into *last.
8976 */
8977 free(curpeers->id);
8978 curpeers = curpeers->next;
8979 free(*last);
8980 *last = curpeers;
8981 }
8982 }
8983
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008984 /* initialize stick-tables on backend capable proxies. This must not
8985 * be done earlier because the data size may be discovered while parsing
8986 * other proxies.
8987 */
8988 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8989 if (curproxy->state == PR_STSTOPPED)
8990 continue;
8991
8992 if (!stktable_init(&curproxy->table)) {
8993 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8994 cfgerr++;
8995 }
8996 }
8997
Simon Horman0d16a402015-01-30 11:22:58 +09008998 if (mailers) {
8999 struct mailers *curmailers = mailers, **last;
9000 struct mailer *m, *mb;
9001
9002 /* Remove all mailers sections which don't have a valid listener.
9003 * This can happen when a mailers section is never referenced.
9004 */
9005 last = &mailers;
9006 while (*last) {
9007 curmailers = *last;
9008 if (curmailers->users) {
9009 last = &curmailers->next;
9010 continue;
9011 }
9012
9013 Warning("Removing incomplete section 'mailers %s'.\n",
9014 curmailers->id);
9015
9016 m = curmailers->mailer_list;
9017 while (m) {
9018 mb = m->next;
9019 free(m->id);
9020 free(m);
9021 m = mb;
9022 }
9023
9024 /* Destroy and unlink this curmailers section.
9025 * Note: curmailers is backed up into *last.
9026 */
9027 free(curmailers->id);
9028 curmailers = curmailers->next;
9029 free(*last);
9030 *last = curmailers;
9031 }
9032 }
9033
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009034 /* Update server_state_file_name to backend name if backend is supposed to use
9035 * a server-state file locally defined and none has been provided */
9036 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9037 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9038 curproxy->server_state_file_name == NULL)
9039 curproxy->server_state_file_name = strdup(curproxy->id);
9040 }
9041
Willy Tarreau34eb6712011-10-24 18:15:04 +02009042 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009043 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009044 MEM_F_SHARED);
9045
Willy Tarreaubb925012009-07-23 13:36:36 +02009046 if (cfgerr > 0)
9047 err_code |= ERR_ALERT | ERR_FATAL;
9048 out:
9049 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009050}
9051
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009052/*
9053 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9054 * parsing sessions.
9055 */
9056void cfg_register_keywords(struct cfg_kw_list *kwl)
9057{
9058 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9059}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009060
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009061/*
9062 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9063 */
9064void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9065{
9066 LIST_DEL(&kwl->list);
9067 LIST_INIT(&kwl->list);
9068}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009069
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009070/* this function register new section in the haproxy configuration file.
9071 * <section_name> is the name of this new section and <section_parser>
9072 * is the called parser. If two section declaration have the same name,
9073 * only the first declared is used.
9074 */
9075int cfg_register_section(char *section_name,
9076 int (*section_parser)(const char *, int, char **, int))
9077{
9078 struct cfg_section *cs;
9079
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009080 list_for_each_entry(cs, &sections, list) {
9081 if (strcmp(cs->section_name, section_name) == 0) {
9082 Alert("register section '%s': already registered.\n", section_name);
9083 return 0;
9084 }
9085 }
9086
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009087 cs = calloc(1, sizeof(*cs));
9088 if (!cs) {
9089 Alert("register section '%s': out of memory.\n", section_name);
9090 return 0;
9091 }
9092
9093 cs->section_name = section_name;
9094 cs->section_parser = section_parser;
9095
9096 LIST_ADDQ(&sections, &cs->list);
9097
9098 return 1;
9099}
9100
Willy Tarreaubaaee002006-06-26 02:48:02 +02009101/*
David Carlier845efb52015-09-25 11:49:18 +01009102 * free all config section entries
9103 */
9104void cfg_unregister_sections(void)
9105{
9106 struct cfg_section *cs, *ics;
9107
9108 list_for_each_entry_safe(cs, ics, &sections, list) {
9109 LIST_DEL(&cs->list);
9110 free(cs);
9111 }
9112}
9113
Christopher Faulet7110b402016-10-26 11:09:44 +02009114void cfg_backup_sections(struct list *backup_sections)
9115{
9116 struct cfg_section *cs, *ics;
9117
9118 list_for_each_entry_safe(cs, ics, &sections, list) {
9119 LIST_DEL(&cs->list);
9120 LIST_ADDQ(backup_sections, &cs->list);
9121 }
9122}
9123
9124void cfg_restore_sections(struct list *backup_sections)
9125{
9126 struct cfg_section *cs, *ics;
9127
9128 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9129 LIST_DEL(&cs->list);
9130 LIST_ADDQ(&sections, &cs->list);
9131 }
9132}
9133
Willy Tarreau659fbf02016-05-26 17:55:28 +02009134__attribute__((constructor))
9135static void cfgparse_init(void)
9136{
9137 /* Register internal sections */
9138 cfg_register_section("listen", cfg_parse_listen);
9139 cfg_register_section("frontend", cfg_parse_listen);
9140 cfg_register_section("backend", cfg_parse_listen);
9141 cfg_register_section("defaults", cfg_parse_listen);
9142 cfg_register_section("global", cfg_parse_global);
9143 cfg_register_section("userlist", cfg_parse_users);
9144 cfg_register_section("peers", cfg_parse_peers);
9145 cfg_register_section("mailers", cfg_parse_mailers);
9146 cfg_register_section("namespace_list", cfg_parse_netns);
9147 cfg_register_section("resolvers", cfg_parse_resolvers);
9148}
9149
David Carlier845efb52015-09-25 11:49:18 +01009150/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009151 * Local variables:
9152 * c-indent-level: 8
9153 * c-basic-offset: 8
9154 * End:
9155 */