blob: 8d049509c7de8ba9f7c143e4df13fa5a29d7590c [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é2c8d7002014-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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int 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 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
Vincent Bernata72d3902016-05-19 11:15:51 +0200283 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Vincent Bernata72d3902016-05-19 11:15:51 +0200294 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 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 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
natalie.chen2d0e45b2015-04-22 14:10:12 +0800542 int i = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200544 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545
546 if (!strcmp(args[0], "global")) { /* new section */
547 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200550 else if (!strcmp(args[0], "ca-base")) {
551#ifdef USE_OPENSSL
552 if (global.ca_base != NULL) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.ca_base = strdup(args[1]);
563#else
564 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567#endif
568 }
569 else if (!strcmp(args[0], "crt-base")) {
570#ifdef USE_OPENSSL
571 if (global.crt_base != NULL) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.crt_base = strdup(args[1]);
582#else
583 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586#endif
587 }
natalie.chen7c92a9b2015-04-07 11:27:02 +0800588 else if (!strcmp(args[0], "email_alert")) {
589 global.email_alert = 1;
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : email_alert Expects email address as argument.\n", file, linenum);
592 global.email_alert = 0;
593 err_code |= ERR_ALERT;
594 goto out;
595 }
natalie.chen2d0e45b2015-04-22 14:10:12 +0800596 strncpy(global.email_from,args[1],50);
597 for (i=0; i<3; i++) {
598 if (*(args[i+2]) != 0)
599 strncpy(global.email_to[i],args[i+2],50);
natalie.chen7c92a9b2015-04-07 11:27:02 +0800600 }
natalie.chen2d0e45b2015-04-22 14:10:12 +0800601
natalie.chen7c92a9b2015-04-07 11:27:02 +0800602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 else if (!strcmp(args[0], "daemon")) {
604 global.mode |= MODE_DAEMON;
605 }
606 else if (!strcmp(args[0], "debug")) {
607 global.mode |= MODE_DEBUG;
608 }
609 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100610 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200612 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100613 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100616 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100618 else if (!strcmp(args[0], "nosplice")) {
619 global.tune.options &= ~GTUNE_USE_SPLICE;
620 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200621 else if (!strcmp(args[0], "nogetaddrinfo")) {
622 global.tune.options &= ~GTUNE_USE_GAI;
623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624 else if (!strcmp(args[0], "quiet")) {
625 global.mode |= MODE_QUIET;
626 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200627 else if (!strcmp(args[0], "tune.maxpollevents")) {
628 if (global.tune.maxpollevents != 0) {
629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200637 }
638 global.tune.maxpollevents = atol(args[1]);
639 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100640 else if (!strcmp(args[0], "tune.maxaccept")) {
641 if (global.tune.maxaccept != 0) {
642 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200643 err_code |= ERR_ALERT;
644 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100645 }
646 if (*(args[1]) == 0) {
647 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
649 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100650 }
651 global.tune.maxaccept = atol(args[1]);
652 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200653 else if (!strcmp(args[0], "tune.chksize")) {
654 if (*(args[1]) == 0) {
655 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
656 err_code |= ERR_ALERT | ERR_FATAL;
657 goto out;
658 }
659 global.tune.chksize = atol(args[1]);
660 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200661#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200662 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
663 global.tune.sslprivatecache = 1;
664 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100665 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.sslcachesize = atol(args[1]);
672 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100673 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
674 unsigned int ssllifetime;
675 const char *res;
676
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682
683 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
684 if (res) {
685 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
686 file, linenum, *res, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690
691 global.tune.ssllifetime = ssllifetime;
692 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100693 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699 global.tune.ssl_max_record = atol(args[1]);
700 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200701 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 global.tune.ssl_default_dh_param = atol(args[1]);
708 if (global.tune.ssl_default_dh_param < 1024) {
709 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200714#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200715 else if (!strcmp(args[0], "tune.bufsize")) {
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.bufsize = atol(args[1]);
Willy Tarreau47c7d632015-09-28 13:49:53 +0200722 if (global.tune.bufsize <= 0) {
723 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
726 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200727 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
728 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100729 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100730 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200731 }
732 else if (!strcmp(args[0], "tune.maxrewrite")) {
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738 global.tune.maxrewrite = atol(args[1]);
739 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
740 global.tune.maxrewrite = global.tune.bufsize / 2;
741 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100742 else if (!strcmp(args[0], "tune.idletimer")) {
743 unsigned int idle;
744 const char *res;
745
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751
752 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
753 if (res) {
754 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
755 file, linenum, *res, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759
760 if (idle > 65535) {
761 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.idle_timer = idle;
766 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100767 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
768 if (global.tune.client_rcvbuf != 0) {
769 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT;
771 goto out;
772 }
773 if (*(args[1]) == 0) {
774 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
778 global.tune.client_rcvbuf = atol(args[1]);
779 }
780 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
781 if (global.tune.server_rcvbuf != 0) {
782 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT;
784 goto out;
785 }
786 if (*(args[1]) == 0) {
787 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
790 }
791 global.tune.server_rcvbuf = atol(args[1]);
792 }
793 else if (!strcmp(args[0], "tune.sndbuf.client")) {
794 if (global.tune.client_sndbuf != 0) {
795 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT;
797 goto out;
798 }
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.client_sndbuf = atol(args[1]);
805 }
806 else if (!strcmp(args[0], "tune.sndbuf.server")) {
807 if (global.tune.server_sndbuf != 0) {
808 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT;
810 goto out;
811 }
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.server_sndbuf = atol(args[1]);
818 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200819 else if (!strcmp(args[0], "tune.pipesize")) {
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.pipesize = atol(args[1]);
826 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100827 else if (!strcmp(args[0], "tune.http.cookielen")) {
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.cookie_len = atol(args[1]) + 1;
834 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200835 else if (!strcmp(args[0], "tune.http.maxhdr")) {
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.tune.max_http_hdr = atol(args[1]);
842 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100843 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
844#ifdef USE_ZLIB
845 if (*args[1]) {
846 global.tune.zlibmemlevel = atoi(args[1]);
847 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
848 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
849 file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
853 } else {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859#else
860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863#endif
864 }
865 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
866#ifdef USE_ZLIB
867 if (*args[1]) {
868 global.tune.zlibwindowsize = atoi(args[1]);
869 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881#else
882 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885#endif
886 }
William Lallemandf3747832012-11-09 12:33:10 +0100887 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
888 if (*args[1]) {
889 global.tune.comp_maxlevel = atoi(args[1]);
890 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
891 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
892 file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
896 } else {
897 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
898 file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 else if (!strcmp(args[0], "uid")) {
904 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200905 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200906 err_code |= ERR_ALERT;
907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
Baptiste Assmann2b429932016-03-11 17:10:04 +0100914 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
915 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]);
916 err_code |= ERR_WARN;
917 goto out;
918 }
919
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 }
921 else if (!strcmp(args[0], "gid")) {
922 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200923 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT;
925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
Baptiste Assmannd5760be2016-03-11 17:21:15 +0100932 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
933 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]);
934 err_code |= ERR_WARN;
935 goto out;
936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200938 /* user/group name handling */
939 else if (!strcmp(args[0], "user")) {
940 struct passwd *ha_user;
941 if (global.uid != 0) {
942 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200945 }
946 errno = 0;
947 ha_user = getpwnam(args[1]);
948 if (ha_user != NULL) {
949 global.uid = (int)ha_user->pw_uid;
950 }
951 else {
952 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 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 }
955 }
956 else if (!strcmp(args[0], "group")) {
957 struct group *ha_group;
958 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200959 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200962 }
963 errno = 0;
964 ha_group = getgrnam(args[1]);
965 if (ha_group != NULL) {
966 global.gid = (int)ha_group->gr_gid;
967 }
968 else {
969 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 +0200970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200971 }
972 }
973 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979 }
980 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100981 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
982 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
983 file, linenum, args[0], LONGBITS, global.nbproc);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 }
988 else if (!strcmp(args[0], "maxconn")) {
989 if (global.maxconn != 0) {
990 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 global.maxconn = atol(args[1]);
1000#ifdef SYSTEM_MAXCONN
1001 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1002 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);
1003 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001004 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006#endif /* SYSTEM_MAXCONN */
1007 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001008 else if (!strcmp(args[0], "maxsslconn")) {
1009#ifdef USE_OPENSSL
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
1014 }
1015 global.maxsslconn = atol(args[1]);
1016#else
Emeric Brun0914df82012-10-02 18:45:42 +02001017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001020#endif
1021 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001022 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1023#ifdef USE_OPENSSL
1024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 free(global.listen_default_ciphers);
1030 global.listen_default_ciphers = strdup(args[1]);
1031#else
1032 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035#endif
1036 }
1037 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1038#ifdef USE_OPENSSL
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 free(global.connect_default_ciphers);
1045 global.connect_default_ciphers = strdup(args[1]);
1046#else
1047 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050#endif
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
1053 if (*(args[1]) == 0) {
1054 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 if (strcmp(args[1],"none") == 0)
1059 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1060 else if (strcmp(args[1],"required") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1062 else {
1063 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001068 else if (!strcmp(args[0], "maxconnrate")) {
1069 if (global.cps_lim != 0) {
1070 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT;
1072 goto out;
1073 }
1074 if (*(args[1]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 global.cps_lim = atol(args[1]);
1080 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001081 else if (!strcmp(args[0], "maxsessrate")) {
1082 if (global.sps_lim != 0) {
1083 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1084 err_code |= ERR_ALERT;
1085 goto out;
1086 }
1087 if (*(args[1]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
1091 }
1092 global.sps_lim = atol(args[1]);
1093 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001094 else if (!strcmp(args[0], "maxsslrate")) {
1095 if (global.ssl_lim != 0) {
1096 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT;
1098 goto out;
1099 }
1100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
1104 }
1105 global.ssl_lim = atol(args[1]);
1106 }
William Lallemandd85f9172012-11-09 17:05:39 +01001107 else if (!strcmp(args[0], "maxcomprate")) {
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.comp_rate_lim = atoi(args[1]) * 1024;
1114 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001115 else if (!strcmp(args[0], "maxpipes")) {
1116 if (global.maxpipes != 0) {
1117 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT;
1119 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001120 }
1121 if (*(args[1]) == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 }
1126 global.maxpipes = atol(args[1]);
1127 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001128 else if (!strcmp(args[0], "maxzlibmem")) {
1129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
William Lallemande3a7d992012-11-20 11:25:20 +01001134 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001135 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001136 else if (!strcmp(args[0], "maxcompcpuusage")) {
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
1141 }
1142 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001143 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001144 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148}
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 else if (!strcmp(args[0], "ulimit-n")) {
1151 if (global.rlimit_nofile != 0) {
1152 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001153 err_code |= ERR_ALERT;
1154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 if (*(args[1]) == 0) {
1157 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 }
1161 global.rlimit_nofile = atol(args[1]);
1162 }
1163 else if (!strcmp(args[0], "chroot")) {
1164 if (global.chroot != NULL) {
1165 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 if (*(args[1]) == 0) {
1170 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 global.chroot = strdup(args[1]);
1175 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001176 else if (!strcmp(args[0], "description")) {
1177 int i, len=0;
1178 char *d;
1179
1180 if (!*args[1]) {
1181 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1182 file, linenum, args[0]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186
Willy Tarreau348acfe2014-04-14 15:00:39 +02001187 for (i = 1; *args[i]; i++)
1188 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001189
1190 if (global.desc)
1191 free(global.desc);
1192
1193 global.desc = d = (char *)calloc(1, len);
1194
Willy Tarreau348acfe2014-04-14 15:00:39 +02001195 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1196 for (i = 2; *args[i]; i++)
1197 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001198 }
1199 else if (!strcmp(args[0], "node")) {
1200 int i;
1201 char c;
1202
1203 for (i=0; args[1][i]; i++) {
1204 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001205 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1206 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207 break;
1208 }
1209
1210 if (!i || args[1][i]) {
1211 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1212 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1213 file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217
1218 if (global.node)
1219 free(global.node);
1220
1221 global.node = strdup(args[1]);
1222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 else if (!strcmp(args[0], "pidfile")) {
1224 if (global.pidfile != NULL) {
1225 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001226 err_code |= ERR_ALERT;
1227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 }
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 global.pidfile = strdup(args[1]);
1235 }
Emeric Bruned760922010-10-22 17:59:25 +02001236 else if (!strcmp(args[0], "unix-bind")) {
1237 int cur_arg = 1;
1238 while (*(args[cur_arg])) {
1239 if (!strcmp(args[cur_arg], "prefix")) {
1240 if (global.unix_bind.prefix != NULL) {
1241 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1242 err_code |= ERR_ALERT;
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (*(args[cur_arg+1]) == 0) {
1248 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1253 cur_arg += 2;
1254 continue;
1255 }
1256
1257 if (!strcmp(args[cur_arg], "mode")) {
1258
1259 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "uid")) {
1265
1266 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1267 cur_arg += 2;
1268 continue;
1269 }
1270
1271 if (!strcmp(args[cur_arg], "gid")) {
1272
1273 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1274 cur_arg += 2;
1275 continue;
1276 }
1277
1278 if (!strcmp(args[cur_arg], "user")) {
1279 struct passwd *user;
1280
1281 user = getpwnam(args[cur_arg + 1]);
1282 if (!user) {
1283 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1284 file, linenum, args[0], args[cur_arg + 1 ]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
1289 global.unix_bind.ux.uid = user->pw_uid;
1290 cur_arg += 2;
1291 continue;
1292 }
1293
1294 if (!strcmp(args[cur_arg], "group")) {
1295 struct group *group;
1296
1297 group = getgrnam(args[cur_arg + 1]);
1298 if (!group) {
1299 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1300 file, linenum, args[0], args[cur_arg + 1 ]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
1305 global.unix_bind.ux.gid = group->gr_gid;
1306 cur_arg += 2;
1307 continue;
1308 }
1309
Willy Tarreaub48f9582011-09-05 01:17:06 +02001310 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001311 file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 }
William Lallemand0f99e342011-10-12 17:50:54 +02001316 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1317 /* delete previous herited or defined syslog servers */
1318 struct logsrv *back;
1319 struct logsrv *tmp;
1320
1321 if (*(args[1]) != 0) {
1322 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326
1327 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1328 LIST_DEL(&tmp->list);
1329 free(tmp);
1330 }
1331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001333 struct sockaddr_storage *sk;
1334 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001335 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001336 int arg = 0;
1337 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001338
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 if (*(args[1]) == 0 || *(args[2]) == 0) {
1340 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
William Lallemand0f99e342011-10-12 17:50:54 +02001344
1345 logsrv = calloc(1, sizeof(struct logsrv));
1346
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001347 /* just after the address, a length may be specified */
1348 if (strcmp(args[arg+2], "len") == 0) {
1349 len = atoi(args[arg+3]);
1350 if (len < 80 || len > 65535) {
1351 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1352 file, linenum, args[arg+3]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356 logsrv->maxlen = len;
1357
1358 /* skip these two args */
1359 arg += 2;
1360 }
1361 else
1362 logsrv->maxlen = MAX_SYSLOG_LEN;
1363
1364 if (logsrv->maxlen > global.max_syslog_len) {
1365 global.max_syslog_len = logsrv->maxlen;
1366 logline = realloc(logline, global.max_syslog_len + 1);
1367 }
1368
1369 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001370 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001371 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001373 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375
William Lallemand0f99e342011-10-12 17:50:54 +02001376 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001377 if (*(args[arg+3])) {
1378 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001379 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001380 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001382 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384 }
1385
William Lallemand0f99e342011-10-12 17:50:54 +02001386 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001387 if (*(args[arg+4])) {
1388 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001389 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001390 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001392 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001393 }
1394 }
1395
Willy Tarreau902636f2013-03-10 19:44:48 +01001396 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001397 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001398 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001400 free(logsrv);
1401 goto out;
1402 }
1403 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001404
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001405 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001406 if (port1 != port2) {
1407 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1408 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001411 goto out;
1412 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001413
William Lallemand0f99e342011-10-12 17:50:54 +02001414 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001415 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001416 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
William Lallemand0f99e342011-10-12 17:50:54 +02001419 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001420 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001421 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1422 char *name;
1423 int len;
1424
1425 if (global.log_send_hostname != NULL) {
1426 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1427 err_code |= ERR_ALERT;
1428 goto out;
1429 }
1430
1431 if (*(args[1]))
1432 name = args[1];
1433 else
1434 name = hostname;
1435
1436 len = strlen(name);
1437
1438 /* We'll add a space after the name to respect the log format */
1439 free(global.log_send_hostname);
1440 global.log_send_hostname = malloc(len + 2);
1441 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1442 }
Kevinm48936af2010-12-22 16:08:21 +00001443 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 free(global.log_tag);
1450 global.log_tag = strdup(args[1]);
1451 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001452 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1453 if (global.spread_checks != 0) {
1454 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 err_code |= ERR_ALERT;
1456 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001457 }
1458 if (*(args[1]) == 0) {
1459 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001462 }
1463 global.spread_checks = atol(args[1]);
1464 if (global.spread_checks < 0 || global.spread_checks > 50) {
1465 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001469 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1470 const char *err;
1471 unsigned int val;
1472
1473
1474 if (*(args[1]) == 0) {
1475 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT | ERR_FATAL;
1477 goto out;
1478 }
1479
1480 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1481 if (err) {
1482 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 }
1485 global.max_spread_checks = val;
1486 if (global.max_spread_checks < 0) {
1487 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 }
1490 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1492#ifdef USE_CPU_AFFINITY
1493 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001494 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001495 unsigned long cpus = 0;
1496
1497 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001498 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001499 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001500 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001501 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001502 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001503 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001504 proc = atol(args[1]);
1505 if (proc >= 1 && proc <= LONGBITS)
1506 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 }
1508
1509 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001510 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",
1511 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
1514 }
1515
1516 cur_arg = 2;
1517 while (*args[cur_arg]) {
1518 unsigned int low, high;
1519
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001520 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 char *dash = strchr(args[cur_arg], '-');
1522
1523 low = high = str2uic(args[cur_arg]);
1524 if (dash)
1525 high = str2uic(dash + 1);
1526
1527 if (high < low) {
1528 unsigned int swap = low;
1529 low = high;
1530 high = swap;
1531 }
1532
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001533 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001534 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001535 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
1540 while (low <= high)
1541 cpus |= 1UL << low++;
1542 }
1543 else {
1544 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1545 file, linenum, args[0], args[cur_arg]);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
1548 }
1549 cur_arg++;
1550 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 for (i = 0; i < LONGBITS; i++)
1552 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001553 global.cpu_map[i] = cpus;
1554#else
1555 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558#endif
1559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001561 struct cfg_kw_list *kwl;
1562 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001563 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001564
1565 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1566 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1567 if (kwl->kw[index].section != CFG_GLOBAL)
1568 continue;
1569 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001570 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001571 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001572 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001574 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001575 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001576 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_WARN;
1578 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001579 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001580 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001581 }
1582 }
1583 }
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001588
Willy Tarreau058e9072009-07-20 09:30:05 +02001589 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592}
1593
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001594void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001596 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 defproxy.mode = PR_MODE_TCP;
1598 defproxy.state = PR_STNEW;
1599 defproxy.maxconn = cfg_maxpconn;
1600 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001601
Simon Horman66183002013-02-23 10:16:43 +09001602 defproxy.defsrv.check.inter = DEF_CHKINTR;
1603 defproxy.defsrv.check.fastinter = 0;
1604 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001605 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1606 defproxy.defsrv.agent.fastinter = 0;
1607 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001608 defproxy.defsrv.check.rise = DEF_RISETIME;
1609 defproxy.defsrv.check.fall = DEF_FALLTIME;
1610 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1611 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001612 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001613 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001614 defproxy.defsrv.maxqueue = 0;
1615 defproxy.defsrv.minconn = 0;
1616 defproxy.defsrv.maxconn = 0;
1617 defproxy.defsrv.slowstart = 0;
1618 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1619 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1620 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621}
1622
Willy Tarreauade5ec42010-01-28 19:33:49 +01001623
Willy Tarreau63af98d2014-05-18 08:11:41 +02001624/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1625 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1626 * ERR_FATAL in case of error.
1627 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001628static int create_cond_regex_rule(const char *file, int line,
1629 struct proxy *px, int dir, int action, int flags,
1630 const char *cmd, const char *reg, const char *repl,
1631 const char **cond_start)
1632{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001633 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001634 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001635 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001636 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001637 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001638 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001639 int cs;
1640 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001641
1642 if (px == &defproxy) {
1643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001645 goto err;
1646 }
1647
1648 if (*reg == 0) {
1649 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001650 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001651 goto err;
1652 }
1653
1654 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001655 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656
Willy Tarreau5321c422010-01-28 20:35:13 +01001657 if (cond_start &&
1658 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001659 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1660 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1661 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001663 goto err;
1664 }
1665 }
1666 else if (cond_start && **cond_start) {
1667 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1668 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001669 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001670 goto err;
1671 }
1672
Willy Tarreau63af98d2014-05-18 08:11:41 +02001673 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001674 (dir == SMP_OPT_DIR_REQ) ?
1675 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1676 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1677 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001678
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001679 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001680 if (!preg) {
1681 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001682 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001683 goto err;
1684 }
1685
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001686 cs = !(flags & REG_ICASE);
1687 cap = !(flags & REG_NOSUB);
1688 error = NULL;
1689 if (!regex_comp(reg, preg, cs, cap, &error)) {
1690 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1691 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001692 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001693 goto err;
1694 }
1695
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001696 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001697 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001698 if (repl && err) {
1699 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1700 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001701 ret_code |= ERR_ALERT | ERR_FATAL;
1702 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001703 }
1704
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001705 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001706 ret_code |= ERR_WARN;
1707
1708 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001709
Willy Tarreau63af98d2014-05-18 08:11:41 +02001710 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001711 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001712 err:
1713 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001714 free(errmsg);
1715 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001716}
1717
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001719 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001720 * Returns the error code, 0 if OK, or any combination of :
1721 * - ERR_ABORT: must abort ASAP
1722 * - ERR_FATAL: we can continue parsing but not start the service
1723 * - ERR_WARN: a warning has been emitted
1724 * - ERR_ALERT: an alert has been emitted
1725 * Only the two first ones can stop processing, the two others are just
1726 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001728int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1729{
1730 static struct peers *curpeers = NULL;
1731 struct peer *newpeer = NULL;
1732 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001733 struct bind_conf *bind_conf;
1734 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001735 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001736 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001737
1738 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001739 if (!*args[1]) {
1740 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001741 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001742 goto out;
1743 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001744
1745 err = invalid_char(args[1]);
1746 if (err) {
1747 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1748 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001749 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001750 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001751 }
1752
1753 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1754 /*
1755 * If there are two proxies with the same name only following
1756 * combinations are allowed:
1757 */
1758 if (strcmp(curpeers->id, args[1]) == 0) {
1759 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1760 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1761 err_code |= ERR_WARN;
1762 }
1763 }
1764
1765 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1766 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1767 err_code |= ERR_ALERT | ERR_ABORT;
1768 goto out;
1769 }
1770
1771 curpeers->next = peers;
1772 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001773 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001774 curpeers->conf.line = linenum;
1775 curpeers->last_change = now.tv_sec;
1776 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001777 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001778 }
1779 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001780 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001781 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001782 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001783
1784 if (!*args[2]) {
1785 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1786 file, linenum, args[0]);
1787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
1789 }
1790
1791 err = invalid_char(args[1]);
1792 if (err) {
1793 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1794 file, linenum, *err, args[1]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
1797 }
1798
1799 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1800 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1801 err_code |= ERR_ALERT | ERR_ABORT;
1802 goto out;
1803 }
1804
1805 /* the peers are linked backwards first */
1806 curpeers->count++;
1807 newpeer->next = curpeers->remote;
1808 curpeers->remote = newpeer;
1809 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001810 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001811 newpeer->conf.line = linenum;
1812
1813 newpeer->last_change = now.tv_sec;
1814 newpeer->id = strdup(args[1]);
1815
Willy Tarreau902636f2013-03-10 19:44:48 +01001816 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001817 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001818 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001819 err_code |= ERR_ALERT | ERR_FATAL;
1820 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001821 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001822
1823 proto = protocol_by_family(sk->ss_family);
1824 if (!proto || !proto->connect) {
1825 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1826 file, linenum, args[0], args[1]);
1827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001830
1831 if (port1 != port2) {
1832 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1833 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 if (!port1) {
1839 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1840 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
1843 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001844
Emeric Brun32da3c42010-09-23 18:39:19 +02001845 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001846 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001847 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001848 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001849
Emeric Brun32da3c42010-09-23 18:39:19 +02001850 if (strcmp(newpeer->id, localpeer) == 0) {
1851 /* Current is local peer, it define a frontend */
1852 newpeer->local = 1;
1853
1854 if (!curpeers->peers_fe) {
1855 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1856 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1857 err_code |= ERR_ALERT | ERR_ABORT;
1858 goto out;
1859 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001860
Willy Tarreau237250c2011-07-29 01:49:03 +02001861 init_new_proxy(curpeers->peers_fe);
1862 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001863
1864 curpeers->peers_fe->last_change = now.tv_sec;
1865 curpeers->peers_fe->id = strdup(args[1]);
1866 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001867 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001868 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001869 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001870 curpeers->peers_fe->accept = peer_accept;
1871 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001872 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1873 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001874 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001875
1876 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1877
Willy Tarreau902636f2013-03-10 19:44:48 +01001878 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1879 if (errmsg && *errmsg) {
1880 indent_msg(&errmsg, 2);
1881 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001882 }
1883 else
1884 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1885 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001886 err_code |= ERR_FATAL;
1887 goto out;
1888 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001889
1890 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001891 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001892 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1893 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1894 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1895 l->accept = session_accept;
1896 l->handler = process_session;
1897 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1898 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1899 global.maxsock += l->maxconn;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001902 else {
1903 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1904 file, linenum, args[0], args[1],
1905 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1906 err_code |= ERR_FATAL;
1907 goto out;
1908 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001909 }
1910 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001911 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1912 curpeers->state = PR_STSTOPPED;
1913 }
1914 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1915 curpeers->state = PR_STNEW;
1916 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001917 else if (*args[0] != 0) {
1918 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
1921 }
1922
1923out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001924 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001925 return err_code;
1926}
1927
Willy Tarreau3842f002009-06-14 11:39:52 +02001928int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929{
1930 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001931 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001932 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001933 int rc;
1934 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001935 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001936 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001937 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001938 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001939 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940
Willy Tarreau977b8e42006-12-29 14:19:17 +01001941 if (!strcmp(args[0], "listen"))
1942 rc = PR_CAP_LISTEN;
1943 else if (!strcmp(args[0], "frontend"))
1944 rc = PR_CAP_FE | PR_CAP_RS;
1945 else if (!strcmp(args[0], "backend"))
1946 rc = PR_CAP_BE | PR_CAP_RS;
1947 else if (!strcmp(args[0], "ruleset"))
1948 rc = PR_CAP_RS;
1949 else
1950 rc = PR_CAP_NONE;
1951
1952 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001953 struct ebpt_node *node;
1954
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 if (!*args[1]) {
1956 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1957 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1958 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_ABORT;
1960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001962
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001963 err = invalid_char(args[1]);
1964 if (err) {
1965 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1966 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001968 }
1969
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001970 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1971 curproxy = container_of(node, struct proxy, conf.by_name);
1972
1973 if (strcmp(curproxy->id, args[1]) != 0)
1974 break;
1975
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001976 /*
1977 * If there are two proxies with the same name only following
1978 * combinations are allowed:
1979 *
1980 * listen backend frontend ruleset
1981 * listen - - - -
1982 * backend - - OK -
1983 * frontend - OK - -
1984 * ruleset - - - -
1985 */
1986
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001987 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1988 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001989 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1990 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1991 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001993 }
1994 }
1995
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1997 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_ALERT | ERR_ABORT;
1999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002001
Willy Tarreau97cb7802010-01-03 20:23:58 +01002002 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 curproxy->next = proxy;
2004 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002005 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2006 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002007 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002009 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002010 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011
2012 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002013 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002014 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002015
Willy Tarreau4348fad2012-09-20 16:48:07 +02002016 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2017
Willy Tarreau902636f2013-03-10 19:44:48 +01002018 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2019 if (errmsg && *errmsg) {
2020 indent_msg(&errmsg, 2);
2021 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002022 }
2023 else
2024 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2025 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_FATAL;
2027 goto out;
2028 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002029
Willy Tarreau4348fad2012-09-20 16:48:07 +02002030 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002031 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
2034
2035 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002036 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002037 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002041 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002042 curproxy->no_options = defproxy.no_options;
2043 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002044 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002045 curproxy->except_net = defproxy.except_net;
2046 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002047 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002048 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002050 if (defproxy.fwdfor_hdr_len) {
2051 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2052 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2053 }
2054
Willy Tarreaub86db342009-11-30 11:50:16 +01002055 if (defproxy.orgto_hdr_len) {
2056 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2057 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2058 }
2059
Mark Lamourinec2247f02012-01-04 13:02:01 -05002060 if (defproxy.server_id_hdr_len) {
2061 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2062 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2063 }
2064
Willy Tarreau977b8e42006-12-29 14:19:17 +01002065 if (curproxy->cap & PR_CAP_FE) {
2066 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002067 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002068 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069
2070 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002071 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2072 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073
2074 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076
Willy Tarreau977b8e42006-12-29 14:19:17 +01002077 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002078 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 curproxy->fullconn = defproxy.fullconn;
2080 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002081 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002083 if (defproxy.check_req) {
2084 curproxy->check_req = calloc(1, defproxy.check_len);
2085 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2086 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002087 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002089 if (defproxy.expect_str) {
2090 curproxy->expect_str = strdup(defproxy.expect_str);
2091 if (defproxy.expect_regex) {
2092 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002093 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2094 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002095 }
2096 }
2097
Willy Tarreau67402132012-05-31 20:40:20 +02002098 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (defproxy.cookie_name)
2100 curproxy->cookie_name = strdup(defproxy.cookie_name);
2101 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002102 if (defproxy.cookie_domain)
2103 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002104
Willy Tarreau31936852010-10-06 16:59:56 +02002105 if (defproxy.cookie_maxidle)
2106 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2107
2108 if (defproxy.cookie_maxlife)
2109 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2110
Emeric Brun647caf12009-06-30 17:57:00 +02002111 if (defproxy.rdp_cookie_name)
2112 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2113 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2114
Willy Tarreau01732802007-11-01 22:48:15 +01002115 if (defproxy.url_param_name)
2116 curproxy->url_param_name = strdup(defproxy.url_param_name);
2117 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002118
Benoitaffb4812009-03-25 13:02:10 +01002119 if (defproxy.hh_name)
2120 curproxy->hh_name = strdup(defproxy.hh_name);
2121 curproxy->hh_len = defproxy.hh_len;
2122 curproxy->hh_match_domain = defproxy.hh_match_domain;
2123
Willy Tarreauef9a3602012-12-08 22:29:20 +01002124 if (defproxy.conn_src.iface_name)
2125 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2126 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002127 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002128#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002129 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002130#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002133 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002134 if (defproxy.capture_name)
2135 curproxy->capture_name = strdup(defproxy.capture_name);
2136 curproxy->capture_namelen = defproxy.capture_namelen;
2137 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139
Willy Tarreau977b8e42006-12-29 14:19:17 +01002140 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002141 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002142 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002143 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002144 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002145 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 curproxy->mon_net = defproxy.mon_net;
2147 curproxy->mon_mask = defproxy.mon_mask;
2148 if (defproxy.monitor_uri)
2149 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2150 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002151 if (defproxy.defbe.name)
2152 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002153
2154 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002155 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2156 if (curproxy->conf.logformat_string &&
2157 curproxy->conf.logformat_string != default_http_log_format &&
2158 curproxy->conf.logformat_string != default_tcp_log_format &&
2159 curproxy->conf.logformat_string != clf_http_log_format)
2160 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2161
2162 if (defproxy.conf.lfs_file) {
2163 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2164 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2165 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002166 }
2167
2168 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002169 curproxy->timeout.connect = defproxy.timeout.connect;
2170 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002171 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002172 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002173 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002174 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002175 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002176 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002177 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002178 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179 }
2180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002182 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002183
2184 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002185 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002186 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002187 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002188 LIST_INIT(&node->list);
2189 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2190 }
2191
Willy Tarreau62a61232013-04-12 18:13:46 +02002192 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2193 if (curproxy->conf.uniqueid_format_string)
2194 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2195
2196 if (defproxy.conf.uif_file) {
2197 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2198 curproxy->conf.uif_line = defproxy.conf.uif_line;
2199 }
William Lallemanda73203e2012-03-12 12:48:57 +01002200
2201 /* copy default header unique id */
2202 if (defproxy.header_unique_id)
2203 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2204
William Lallemand82fe75c2012-10-23 10:25:10 +02002205 /* default compression options */
2206 if (defproxy.comp != NULL) {
2207 curproxy->comp = calloc(1, sizeof(struct comp));
2208 curproxy->comp->algos = defproxy.comp->algos;
2209 curproxy->comp->types = defproxy.comp->types;
2210 }
2211
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002213 curproxy->conf.used_listener_id = EB_ROOT;
2214 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002215
Willy Tarreau93893792009-07-23 13:19:11 +02002216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 }
2218 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2219 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002220 /* FIXME-20070101: we should do this too at the end of the
2221 * config parsing to free all default values.
2222 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002223 free(defproxy.check_req);
2224 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002225 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002226 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002228 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002229 free(defproxy.capture_name);
2230 free(defproxy.monitor_uri);
2231 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002232 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002233 free(defproxy.fwdfor_hdr_name);
2234 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002235 free(defproxy.orgto_hdr_name);
2236 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002237 free(defproxy.server_id_hdr_name);
2238 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002239 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002240 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002241 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002242 free(defproxy.expect_regex);
2243 defproxy.expect_regex = NULL;
2244 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002245
Willy Tarreau62a61232013-04-12 18:13:46 +02002246 if (defproxy.conf.logformat_string != default_http_log_format &&
2247 defproxy.conf.logformat_string != default_tcp_log_format &&
2248 defproxy.conf.logformat_string != clf_http_log_format)
2249 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002250
Willy Tarreau62a61232013-04-12 18:13:46 +02002251 free(defproxy.conf.uniqueid_format_string);
2252 free(defproxy.conf.lfs_file);
2253 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002254
Willy Tarreaua534fea2008-08-03 12:19:50 +02002255 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002256 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 /* we cannot free uri_auth because it might already be used */
2259 init_default_instance();
2260 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002261 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2262 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
2266 else if (curproxy == NULL) {
2267 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002271
2272 /* update the current file and line being parsed */
2273 curproxy->conf.args.file = curproxy->conf.file;
2274 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275
2276 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002277 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2278 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2279 if (err_code & ERR_FATAL)
2280 goto out;
2281 }
2282 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002283 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002284 int cur_arg;
2285
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 if (curproxy == &defproxy) {
2287 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293
Willy Tarreau24709282013-03-10 21:32:12 +01002294 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002295 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002300
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002301 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002302
2303 /* use default settings for unix sockets */
2304 bind_conf->ux.uid = global.unix_bind.ux.uid;
2305 bind_conf->ux.gid = global.unix_bind.ux.gid;
2306 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002307
2308 /* NOTE: the following line might create several listeners if there
2309 * are comma-separated IPs or port ranges. So all further processing
2310 * will have to be applied to all listeners created after last_listen.
2311 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002312 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2313 if (errmsg && *errmsg) {
2314 indent_msg(&errmsg, 2);
2315 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002316 }
2317 else
2318 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2319 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002323
Willy Tarreau4348fad2012-09-20 16:48:07 +02002324 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2325 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002326 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002327 }
2328
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002329 cur_arg = 2;
2330 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002331 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002332 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002333 char *err;
2334
Willy Tarreau26982662012-09-12 23:17:10 +02002335 kw = bind_find_kw(args[cur_arg]);
2336 if (kw) {
2337 char *err = NULL;
2338 int code;
2339
2340 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002341 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2342 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002343 cur_arg += 1 + kw->skip ;
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347
Willy Tarreau4348fad2012-09-20 16:48:07 +02002348 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002349 err_code |= code;
2350
2351 if (code) {
2352 if (err && *err) {
2353 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002354 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002355 }
2356 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002357 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2358 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002359 if (code & ERR_FATAL) {
2360 free(err);
2361 cur_arg += 1 + kw->skip;
2362 goto out;
2363 }
2364 }
2365 free(err);
2366 cur_arg += 1 + kw->skip;
2367 continue;
2368 }
2369
Willy Tarreau8638f482012-09-18 18:01:17 +02002370 err = NULL;
2371 if (!bind_dumped) {
2372 bind_dump_kws(&err);
2373 indent_msg(&err, 4);
2374 bind_dumped = 1;
2375 }
2376
2377 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2378 file, linenum, args[0], args[1], args[cur_arg],
2379 err ? " Registered keywords :" : "", err ? err : "");
2380 free(err);
2381
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002384 }
Willy Tarreau93893792009-07-23 13:19:11 +02002385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
2387 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002388 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 /* flush useless bits */
2398 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002401 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404
Willy Tarreau1c47f852006-07-09 08:22:27 +02002405 if (!*args[1]) {
2406 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2407 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002410 }
2411
Willy Tarreaua534fea2008-08-03 12:19:50 +02002412 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002413 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002414 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002415 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002416 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2417
Willy Tarreau93893792009-07-23 13:19:11 +02002418 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2421 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2422 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2423 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2424 else {
2425 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002430 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002431 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002432
2433 if (curproxy == &defproxy) {
2434 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2435 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002438 }
2439
2440 if (!*args[1]) {
2441 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002445 }
2446
2447 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002448 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002449
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002450 if (curproxy->uuid <= 0) {
2451 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002452 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002455 }
2456
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002457 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2458 if (node) {
2459 struct proxy *target = container_of(node, struct proxy, conf.id);
2460 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2461 file, linenum, proxy_type_str(curproxy), curproxy->id,
2462 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002467 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002468 else if (!strcmp(args[0], "description")) {
2469 int i, len=0;
2470 char *d;
2471
Cyril Bonté99ed3272010-01-24 23:29:44 +01002472 if (curproxy == &defproxy) {
2473 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2474 file, linenum, args[0]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002479 if (!*args[1]) {
2480 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2481 file, linenum, args[0]);
2482 return -1;
2483 }
2484
Willy Tarreau348acfe2014-04-14 15:00:39 +02002485 for (i = 1; *args[i]; i++)
2486 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002487
2488 d = (char *)calloc(1, len);
2489 curproxy->desc = d;
2490
Willy Tarreau348acfe2014-04-14 15:00:39 +02002491 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2492 for (i = 2; *args[i]; i++)
2493 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002494
2495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2497 curproxy->state = PR_STSTOPPED;
2498 }
2499 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2500 curproxy->state = PR_STNEW;
2501 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002502 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2503 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002504 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002505
2506 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002507 unsigned int low, high;
2508
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002509 if (strcmp(args[cur_arg], "all") == 0) {
2510 set = 0;
2511 break;
2512 }
2513 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002515 }
2516 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002517 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002518 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002519 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002520 char *dash = strchr(args[cur_arg], '-');
2521
2522 low = high = str2uic(args[cur_arg]);
2523 if (dash)
2524 high = str2uic(dash + 1);
2525
2526 if (high < low) {
2527 unsigned int swap = low;
2528 low = high;
2529 high = swap;
2530 }
2531
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002532 if (low < 1 || high > LONGBITS) {
2533 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2534 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002537 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002538 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002539 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002540 }
2541 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002542 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2543 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002546 }
2547 cur_arg++;
2548 }
2549 curproxy->bind_proc = set;
2550 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002551 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002552 if (curproxy == &defproxy) {
2553 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002556 }
2557
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002558 err = invalid_char(args[1]);
2559 if (err) {
2560 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2561 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002563 }
2564
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002565 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002566 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2567 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002570 }
2571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2573 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574
Willy Tarreau977b8e42006-12-29 14:19:17 +01002575 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 if (*(args[1]) == 0) {
2579 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2580 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002584
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002586 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002587 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002588 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 curproxy->cookie_name = strdup(args[1]);
2590 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002591
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 cur_arg = 2;
2593 while (*(args[cur_arg])) {
2594 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002595 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002598 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 }
2600 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002601 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
2603 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002604 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
2606 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002607 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002609 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002610 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002613 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002615 else if (!strcmp(args[cur_arg], "httponly")) {
2616 curproxy->ck_opts |= PR_CK_HTTPONLY;
2617 }
2618 else if (!strcmp(args[cur_arg], "secure")) {
2619 curproxy->ck_opts |= PR_CK_SECURE;
2620 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002621 else if (!strcmp(args[cur_arg], "domain")) {
2622 if (!*args[cur_arg + 1]) {
2623 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2624 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002627 }
2628
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002629 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002630 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002631 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2632 " dots nor does not start with a dot."
2633 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002634 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002635 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002636 }
2637
2638 err = invalid_domainchar(args[cur_arg + 1]);
2639 if (err) {
2640 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2641 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002644 }
2645
Willy Tarreau68a897b2009-12-03 23:28:34 +01002646 if (!curproxy->cookie_domain) {
2647 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2648 } else {
2649 /* one domain was already specified, add another one by
2650 * building the string which will be returned along with
2651 * the cookie.
2652 */
2653 char *new_ptr;
2654 int new_len = strlen(curproxy->cookie_domain) +
2655 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2656 new_ptr = malloc(new_len);
2657 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2658 free(curproxy->cookie_domain);
2659 curproxy->cookie_domain = new_ptr;
2660 }
Willy Tarreau31936852010-10-06 16:59:56 +02002661 cur_arg++;
2662 }
2663 else if (!strcmp(args[cur_arg], "maxidle")) {
2664 unsigned int maxidle;
2665 const char *res;
2666
2667 if (!*args[cur_arg + 1]) {
2668 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2669 file, linenum, args[cur_arg]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673
2674 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2675 if (res) {
2676 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2677 file, linenum, *res, args[cur_arg]);
2678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
2680 }
2681 curproxy->cookie_maxidle = maxidle;
2682 cur_arg++;
2683 }
2684 else if (!strcmp(args[cur_arg], "maxlife")) {
2685 unsigned int maxlife;
2686 const char *res;
2687
2688 if (!*args[cur_arg + 1]) {
2689 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2690 file, linenum, args[cur_arg]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694
2695 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2696 if (res) {
2697 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2698 file, linenum, *res, args[cur_arg]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002703 cur_arg++;
2704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002706 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 +02002707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
2711 cur_arg++;
2712 }
Willy Tarreau67402132012-05-31 20:40:20 +02002713 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2715 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
2718
Willy Tarreau67402132012-05-31 20:40:20 +02002719 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2721 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002724
Willy Tarreau67402132012-05-31 20:40:20 +02002725 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002726 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2727 file, linenum);
2728 err_code |= ERR_ALERT | ERR_FATAL;
2729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002731 else if (!strcmp(args[0], "persist")) { /* persist */
2732 if (*(args[1]) == 0) {
2733 Alert("parsing [%s:%d] : missing persist method.\n",
2734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002737 }
2738
2739 if (!strncmp(args[1], "rdp-cookie", 10)) {
2740 curproxy->options2 |= PR_O2_RDPC_PRST;
2741
Emeric Brunb982a3d2010-01-04 15:45:53 +01002742 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002743 const char *beg, *end;
2744
2745 beg = args[1] + 11;
2746 end = strchr(beg, ')');
2747
2748 if (!end || end == beg) {
2749 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2750 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002753 }
2754
2755 free(curproxy->rdp_cookie_name);
2756 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2757 curproxy->rdp_cookie_len = end-beg;
2758 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002760 free(curproxy->rdp_cookie_name);
2761 curproxy->rdp_cookie_name = strdup("msts");
2762 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2763 }
2764 else { /* syntax */
2765 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2766 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002769 }
2770 }
2771 else {
2772 Alert("parsing [%s:%d] : unknown persist method.\n",
2773 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002776 }
2777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002779 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002781 if (curproxy == &defproxy) {
2782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002791 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
2796 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 curproxy->appsession_name = strdup(args[1]);
2799 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2800 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002801 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2802 if (err) {
2803 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2804 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002807 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002808 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002809
Willy Tarreau51041c72007-09-09 21:56:53 +02002810 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2811 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_ABORT;
2813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002815
2816 cur_arg = 6;
2817 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2819 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002820 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002821 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002822 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002823 } else if (!strcmp(args[cur_arg], "prefix")) {
2824 curproxy->options2 |= PR_O2_AS_PFX;
2825 } else if (!strcmp(args[cur_arg], "mode")) {
2826 if (!*args[cur_arg + 1]) {
2827 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2828 file, linenum, args[0], args[cur_arg]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832
2833 cur_arg++;
2834 if (!strcmp(args[cur_arg], "query-string")) {
2835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2836 curproxy->options2 |= PR_O2_AS_M_QS;
2837 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2838 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2839 curproxy->options2 |= PR_O2_AS_M_PP;
2840 } else {
2841 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002846 cur_arg++;
2847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 } /* Url App Session */
2849 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002850 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002851 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002852
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002854 if (curproxy == &defproxy) {
2855 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 if (*(args[4]) == 0) {
2861 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2862 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002866 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 curproxy->capture_name = strdup(args[2]);
2868 curproxy->capture_namelen = strlen(curproxy->capture_name);
2869 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 curproxy->to_log |= LW_COOKIE;
2871 }
2872 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2873 struct cap_hdr *hdr;
2874
2875 if (curproxy == &defproxy) {
2876 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 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
2880
2881 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2882 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2883 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
2887
2888 hdr = calloc(sizeof(struct cap_hdr), 1);
2889 hdr->next = curproxy->req_cap;
2890 hdr->name = strdup(args[3]);
2891 hdr->namelen = strlen(args[3]);
2892 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002893 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 hdr->index = curproxy->nb_req_cap++;
2895 curproxy->req_cap = hdr;
2896 curproxy->to_log |= LW_REQHDR;
2897 }
2898 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2899 struct cap_hdr *hdr;
2900
2901 if (curproxy == &defproxy) {
2902 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 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
2906
2907 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2908 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2909 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
2913 hdr = calloc(sizeof(struct cap_hdr), 1);
2914 hdr->next = curproxy->rsp_cap;
2915 hdr->name = strdup(args[3]);
2916 hdr->namelen = strlen(args[3]);
2917 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002918 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 hdr->index = curproxy->nb_rsp_cap++;
2920 curproxy->rsp_cap = hdr;
2921 curproxy->to_log |= LW_RSPHDR;
2922 }
2923 else {
2924 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
2929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002933
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 }
2940 curproxy->conn_retries = atol(args[1]);
2941 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002942 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002943 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002944
2945 if (curproxy == &defproxy) {
2946 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
2949 }
2950
Willy Tarreau20b0de52012-12-24 15:45:22 +01002951 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2952 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2953 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2954 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002955 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002956 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2957 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 +01002958 file, linenum, args[0]);
2959 err_code |= ERR_WARN;
2960 }
2961
Willy Tarreauff011f22011-01-06 17:51:27 +01002962 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002963
Willy Tarreauff011f22011-01-06 17:51:27 +01002964 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002965 err_code |= ERR_ALERT | ERR_ABORT;
2966 goto out;
2967 }
2968
Willy Tarreau5002f572014-04-23 01:32:02 +02002969 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002970 err_code |= warnif_cond_conflicts(rule->cond,
2971 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2972 file, linenum);
2973
Willy Tarreauff011f22011-01-06 17:51:27 +01002974 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002975 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002976 else if (!strcmp(args[0], "http-response")) { /* response access control */
2977 struct http_res_rule *rule;
2978
2979 if (curproxy == &defproxy) {
2980 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984
2985 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2986 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2987 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2988 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2989 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2990 file, linenum, args[0]);
2991 err_code |= ERR_WARN;
2992 }
2993
2994 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2995
2996 if (!rule) {
2997 err_code |= ERR_ALERT | ERR_ABORT;
2998 goto out;
2999 }
3000
3001 err_code |= warnif_cond_conflicts(rule->cond,
3002 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3003 file, linenum);
3004
3005 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3006 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003007 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3008 /* set the header name and length into the proxy structure */
3009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3010 err_code |= ERR_WARN;
3011
3012 if (!*args[1]) {
3013 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3014 file, linenum, args[0]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018
3019 /* set the desired header name */
3020 free(curproxy->server_id_hdr_name);
3021 curproxy->server_id_hdr_name = strdup(args[1]);
3022 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3023 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003024 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003025 struct http_req_rule *rule;
3026
Willy Tarreaub099aca2008-10-12 17:26:37 +02003027 if (curproxy == &defproxy) {
3028 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003031 }
3032
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003033 /* emulate "block" using "http-request block". Since these rules are supposed to
3034 * be processed before all http-request rules, we put them into their own list
3035 * and will insert them at the end.
3036 */
3037 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3038 if (!rule) {
3039 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003040 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003041 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003042 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3043 err_code |= warnif_cond_conflicts(rule->cond,
3044 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3045 file, linenum);
3046 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003047
3048 if (!already_warned(WARN_BLOCK_DEPRECATED))
3049 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]);
3050
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003051 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003052 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003053 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003054
Cyril Bonté99ed3272010-01-24 23:29:44 +01003055 if (curproxy == &defproxy) {
3056 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003061 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003062 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3063 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003066 }
3067
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003068 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003069 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003070 err_code |= warnif_cond_conflicts(rule->cond,
3071 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3072 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003073 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003074 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003075 struct switching_rule *rule;
3076
Willy Tarreaub099aca2008-10-12 17:26:37 +02003077 if (curproxy == &defproxy) {
3078 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003081 }
3082
Willy Tarreau55ea7572007-06-17 19:56:27 +02003083 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003085
3086 if (*(args[1]) == 0) {
3087 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003090 }
3091
Willy Tarreauf51658d2014-04-23 01:21:56 +02003092 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3093 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3094 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3095 file, linenum, errmsg);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003099
Willy Tarreauf51658d2014-04-23 01:21:56 +02003100 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003101 }
3102
3103 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3104 rule->cond = cond;
3105 rule->be.name = strdup(args[1]);
3106 LIST_INIT(&rule->list);
3107 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3108 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003109 else if (strcmp(args[0], "use-server") == 0) {
3110 struct server_rule *rule;
3111
3112 if (curproxy == &defproxy) {
3113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
3118 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3119 err_code |= ERR_WARN;
3120
3121 if (*(args[1]) == 0) {
3122 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126
3127 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3128 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3129 file, linenum, args[0]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003134 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3135 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3136 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003141 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003142
3143 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3144 rule->cond = cond;
3145 rule->srv.name = strdup(args[1]);
3146 LIST_INIT(&rule->list);
3147 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3148 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3149 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003150 else if ((!strcmp(args[0], "force-persist")) ||
3151 (!strcmp(args[0], "ignore-persist"))) {
3152 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003153
3154 if (curproxy == &defproxy) {
3155 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
3158 }
3159
3160 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3161 err_code |= ERR_WARN;
3162
Willy Tarreauef6494c2010-01-28 17:12:36 +01003163 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003164 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3165 file, linenum, args[0]);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
3168 }
3169
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003170 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3171 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3172 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003177 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3178 * where force-persist is applied.
3179 */
3180 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003181
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003182 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003183 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003184 if (!strcmp(args[0], "force-persist")) {
3185 rule->type = PERSIST_TYPE_FORCE;
3186 } else {
3187 rule->type = PERSIST_TYPE_IGNORE;
3188 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003189 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003190 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003191 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 else if (!strcmp(args[0], "stick-table")) {
3193 int myidx = 1;
3194
Emeric Brun32da3c42010-09-23 18:39:19 +02003195 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 curproxy->table.type = (unsigned int)-1;
3197 while (*args[myidx]) {
3198 const char *err;
3199
3200 if (strcmp(args[myidx], "size") == 0) {
3201 myidx++;
3202 if (!*(args[myidx])) {
3203 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3204 file, linenum, args[myidx-1]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
3208 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3209 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3210 file, linenum, *err, args[myidx-1]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003214 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003215 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003216 else if (strcmp(args[myidx], "peers") == 0) {
3217 myidx++;
Godbach50523162013-12-11 19:48:57 +08003218 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003219 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3220 file, linenum, args[myidx-1]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Godbach50523162013-12-11 19:48:57 +08003223 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003224 curproxy->table.peers.name = strdup(args[myidx++]);
3225 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003226 else if (strcmp(args[myidx], "expire") == 0) {
3227 myidx++;
3228 if (!*(args[myidx])) {
3229 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3230 file, linenum, args[myidx-1]);
3231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
3233 }
3234 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3235 if (err) {
3236 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3237 file, linenum, *err, args[myidx-1]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
Ben Cabot85a1c182016-01-20 09:44:39 +00003241 if (val > INT_MAX) {
3242 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3243 file, linenum, val);
3244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
3246 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003248 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 }
3250 else if (strcmp(args[myidx], "nopurge") == 0) {
3251 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003252 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003253 }
3254 else if (strcmp(args[myidx], "type") == 0) {
3255 myidx++;
3256 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3257 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3258 file, linenum, args[myidx]);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003262 /* myidx already points to next arg */
3263 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003264 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003265 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003266 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003267
3268 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003269 nw = args[myidx];
3270 while (*nw) {
3271 /* the "store" keyword supports a comma-separated list */
3272 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003273 sa = NULL; /* store arg */
3274 while (*nw && *nw != ',') {
3275 if (*nw == '(') {
3276 *nw = 0;
3277 sa = ++nw;
3278 while (*nw != ')') {
3279 if (!*nw) {
3280 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3281 file, linenum, args[0], cw);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284 }
3285 nw++;
3286 }
3287 *nw = '\0';
3288 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003289 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003290 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003291 if (*nw)
3292 *nw++ = '\0';
3293 type = stktable_get_data_type(cw);
3294 if (type < 0) {
3295 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3296 file, linenum, args[0], cw);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299 }
Willy Tarreauac782882010-06-20 10:41:54 +02003300
3301 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3302 switch (err) {
3303 case PE_NONE: break;
3304 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003305 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3306 file, linenum, args[0], cw);
3307 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003308 break;
3309
3310 case PE_ARG_MISSING:
3311 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3312 file, linenum, args[0], cw);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315
3316 case PE_ARG_NOT_USED:
3317 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3318 file, linenum, args[0], cw);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321
3322 default:
3323 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3324 file, linenum, args[0], cw);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003327 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003328 }
3329 myidx++;
3330 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003331 else {
3332 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3333 file, linenum, args[myidx]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003336 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003337 }
3338
3339 if (!curproxy->table.size) {
3340 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3341 file, linenum);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345
3346 if (curproxy->table.type == (unsigned int)-1) {
3347 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3348 file, linenum);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 }
3353 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003354 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003355 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003356 int myidx = 0;
3357 const char *name = NULL;
3358 int flags;
3359
3360 if (curproxy == &defproxy) {
3361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365
3366 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3367 err_code |= ERR_WARN;
3368 goto out;
3369 }
3370
3371 myidx++;
3372 if ((strcmp(args[myidx], "store") == 0) ||
3373 (strcmp(args[myidx], "store-request") == 0)) {
3374 myidx++;
3375 flags = STK_IS_STORE;
3376 }
3377 else if (strcmp(args[myidx], "store-response") == 0) {
3378 myidx++;
3379 flags = STK_IS_STORE | STK_ON_RSP;
3380 }
3381 else if (strcmp(args[myidx], "match") == 0) {
3382 myidx++;
3383 flags = STK_IS_MATCH;
3384 }
3385 else if (strcmp(args[myidx], "on") == 0) {
3386 myidx++;
3387 flags = STK_IS_MATCH | STK_IS_STORE;
3388 }
3389 else {
3390 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (*(args[myidx]) == 0) {
3396 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003401 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003402 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003404 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408
3409 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003410 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3411 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3412 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003413 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003414 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003415 goto out;
3416 }
3417 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003418 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3419 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3420 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003421 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003422 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003423 goto out;
3424 }
3425 }
3426
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003427 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003428 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003429
Emeric Brunb982a3d2010-01-04 15:45:53 +01003430 if (strcmp(args[myidx], "table") == 0) {
3431 myidx++;
3432 name = args[myidx++];
3433 }
3434
Willy Tarreauef6494c2010-01-28 17:12:36 +01003435 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003436 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3437 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3438 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003439 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003440 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003441 goto out;
3442 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003443 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003444 else if (*(args[myidx])) {
3445 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3446 file, linenum, args[0], args[myidx]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003448 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003449 goto out;
3450 }
Emeric Brun97679e72010-09-23 17:56:44 +02003451 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003452 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003453 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003454 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003455
Emeric Brunb982a3d2010-01-04 15:45:53 +01003456 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3457 rule->cond = cond;
3458 rule->expr = expr;
3459 rule->flags = flags;
3460 rule->table.name = name ? strdup(name) : NULL;
3461 LIST_INIT(&rule->list);
3462 if (flags & STK_ON_RSP)
3463 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3464 else
3465 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 else if (!strcmp(args[0], "stats")) {
3468 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3469 curproxy->uri_auth = NULL; /* we must detach from the default config */
3470
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003471 if (!*args[1]) {
3472 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003473 } else if (!strcmp(args[1], "admin")) {
3474 struct stats_admin_rule *rule;
3475
3476 if (curproxy == &defproxy) {
3477 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481
3482 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3483 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3484 err_code |= ERR_ALERT | ERR_ABORT;
3485 goto out;
3486 }
3487
3488 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3489 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3490 file, linenum, args[0], args[1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003494 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3495 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3496 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003501 err_code |= warnif_cond_conflicts(cond,
3502 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3503 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003504
3505 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3506 rule->cond = cond;
3507 LIST_INIT(&rule->list);
3508 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 } else if (!strcmp(args[1], "uri")) {
3510 if (*(args[2]) == 0) {
3511 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3515 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_ABORT;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 } else if (!strcmp(args[1], "realm")) {
3520 if (*(args[2]) == 0) {
3521 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3525 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_ABORT;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003529 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003530 unsigned interval;
3531
3532 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3533 if (err) {
3534 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3535 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003538 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_ABORT;
3541 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003542 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003543 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003544 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003545
3546 if (curproxy == &defproxy) {
3547 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
3550 }
3551
3552 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3553 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3554 err_code |= ERR_ALERT | ERR_ABORT;
3555 goto out;
3556 }
3557
Willy Tarreauff011f22011-01-06 17:51:27 +01003558 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3559 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003560 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3561 file, linenum, args[0]);
3562 err_code |= ERR_WARN;
3563 }
3564
Willy Tarreauff011f22011-01-06 17:51:27 +01003565 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003566
Willy Tarreauff011f22011-01-06 17:51:27 +01003567 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003568 err_code |= ERR_ALERT | ERR_ABORT;
3569 goto out;
3570 }
3571
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003572 err_code |= warnif_cond_conflicts(rule->cond,
3573 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3574 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003575 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003576
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 } else if (!strcmp(args[1], "auth")) {
3578 if (*(args[2]) == 0) {
3579 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3583 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_ABORT;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587 } else if (!strcmp(args[1], "scope")) {
3588 if (*(args[2]) == 0) {
3589 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_ABORT;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597 } else if (!strcmp(args[1], "enable")) {
3598 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3599 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_ABORT;
3601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003603 } else if (!strcmp(args[1], "hide-version")) {
3604 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_ABORT;
3607 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003608 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003609 } else if (!strcmp(args[1], "show-legends")) {
3610 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3611 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3612 err_code |= ERR_ALERT | ERR_ABORT;
3613 goto out;
3614 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003615 } else if (!strcmp(args[1], "show-node")) {
3616
3617 if (*args[2]) {
3618 int i;
3619 char c;
3620
3621 for (i=0; args[2][i]; i++) {
3622 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003623 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3624 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003625 break;
3626 }
3627
3628 if (!i || args[2][i]) {
3629 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3630 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 }
3636
3637 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3638 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3639 err_code |= ERR_ALERT | ERR_ABORT;
3640 goto out;
3641 }
3642 } else if (!strcmp(args[1], "show-desc")) {
3643 char *desc = NULL;
3644
3645 if (*args[2]) {
3646 int i, len=0;
3647 char *d;
3648
Willy Tarreau348acfe2014-04-14 15:00:39 +02003649 for (i = 2; *args[i]; i++)
3650 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003651
3652 desc = d = (char *)calloc(1, len);
3653
Willy Tarreau348acfe2014-04-14 15:00:39 +02003654 d += snprintf(d, desc + len - d, "%s", args[2]);
3655 for (i = 3; *args[i]; i++)
3656 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003657 }
3658
3659 if (!*args[2] && !global.desc)
3660 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3661 file, linenum, args[1]);
3662 else {
3663 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3664 free(desc);
3665 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3666 err_code |= ERR_ALERT | ERR_ABORT;
3667 goto out;
3668 }
3669 free(desc);
3670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003672stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003673 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 +01003674 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 }
3679 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003680 int optnum;
3681
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003682 if (*(args[1]) == '\0') {
3683 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003688
3689 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3690 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003691 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3692 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3693 file, linenum, cfg_opts[optnum].name);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
Willy Tarreau93893792009-07-23 13:19:11 +02003697 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3698 err_code |= ERR_WARN;
3699 goto out;
3700 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003701
Willy Tarreau3842f002009-06-14 11:39:52 +02003702 curproxy->no_options &= ~cfg_opts[optnum].val;
3703 curproxy->options &= ~cfg_opts[optnum].val;
3704
3705 switch (kwm) {
3706 case KWM_STD:
3707 curproxy->options |= cfg_opts[optnum].val;
3708 break;
3709 case KWM_NO:
3710 curproxy->no_options |= cfg_opts[optnum].val;
3711 break;
3712 case KWM_DEF: /* already cleared */
3713 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003714 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003715
Willy Tarreau93893792009-07-23 13:19:11 +02003716 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003717 }
3718 }
3719
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003720 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3721 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003722 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3723 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3724 file, linenum, cfg_opts2[optnum].name);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
Willy Tarreau93893792009-07-23 13:19:11 +02003728 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3729 err_code |= ERR_WARN;
3730 goto out;
3731 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003732
Willy Tarreau3842f002009-06-14 11:39:52 +02003733 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3734 curproxy->options2 &= ~cfg_opts2[optnum].val;
3735
3736 switch (kwm) {
3737 case KWM_STD:
3738 curproxy->options2 |= cfg_opts2[optnum].val;
3739 break;
3740 case KWM_NO:
3741 curproxy->no_options2 |= cfg_opts2[optnum].val;
3742 break;
3743 case KWM_DEF: /* already cleared */
3744 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003745 }
Willy Tarreau93893792009-07-23 13:19:11 +02003746 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003747 }
3748 }
3749
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003750 /* HTTP options override each other. They can be cancelled using
3751 * "no option xxx" which only switches to default mode if the mode
3752 * was this one (useful for cancelling options set in defaults
3753 * sections).
3754 */
3755 if (strcmp(args[1], "httpclose") == 0) {
3756 if (kwm == KWM_STD) {
3757 curproxy->options &= ~PR_O_HTTP_MODE;
3758 curproxy->options |= PR_O_HTTP_PCL;
3759 goto out;
3760 }
3761 else if (kwm == KWM_NO) {
3762 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3763 curproxy->options &= ~PR_O_HTTP_MODE;
3764 goto out;
3765 }
3766 }
3767 else if (strcmp(args[1], "forceclose") == 0) {
3768 if (kwm == KWM_STD) {
3769 curproxy->options &= ~PR_O_HTTP_MODE;
3770 curproxy->options |= PR_O_HTTP_FCL;
3771 goto out;
3772 }
3773 else if (kwm == KWM_NO) {
3774 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3775 curproxy->options &= ~PR_O_HTTP_MODE;
3776 goto out;
3777 }
3778 }
3779 else if (strcmp(args[1], "http-server-close") == 0) {
3780 if (kwm == KWM_STD) {
3781 curproxy->options &= ~PR_O_HTTP_MODE;
3782 curproxy->options |= PR_O_HTTP_SCL;
3783 goto out;
3784 }
3785 else if (kwm == KWM_NO) {
3786 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3787 curproxy->options &= ~PR_O_HTTP_MODE;
3788 goto out;
3789 }
3790 }
3791 else if (strcmp(args[1], "http-keep-alive") == 0) {
3792 if (kwm == KWM_STD) {
3793 curproxy->options &= ~PR_O_HTTP_MODE;
3794 curproxy->options |= PR_O_HTTP_KAL;
3795 goto out;
3796 }
3797 else if (kwm == KWM_NO) {
3798 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3799 curproxy->options &= ~PR_O_HTTP_MODE;
3800 goto out;
3801 }
3802 }
3803 else if (strcmp(args[1], "http-tunnel") == 0) {
3804 if (kwm == KWM_STD) {
3805 curproxy->options &= ~PR_O_HTTP_MODE;
3806 curproxy->options |= PR_O_HTTP_TUN;
3807 goto out;
3808 }
3809 else if (kwm == KWM_NO) {
3810 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3811 curproxy->options &= ~PR_O_HTTP_MODE;
3812 goto out;
3813 }
3814 }
3815
Willy Tarreau3842f002009-06-14 11:39:52 +02003816 if (kwm != KWM_STD) {
3817 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003818 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003821 }
3822
Emeric Brun3a058f32009-06-30 18:26:00 +02003823 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003824 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003826 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003827 if (*(args[2]) != '\0') {
3828 if (!strcmp(args[2], "clf")) {
3829 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003830 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003831 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003832 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003835 }
3836 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003837 if (curproxy->conf.logformat_string != default_http_log_format &&
3838 curproxy->conf.logformat_string != default_tcp_log_format &&
3839 curproxy->conf.logformat_string != clf_http_log_format)
3840 free(curproxy->conf.logformat_string);
3841 curproxy->conf.logformat_string = logformat;
3842
3843 free(curproxy->conf.lfs_file);
3844 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3845 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003846 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003847 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003849 if (curproxy->conf.logformat_string != default_http_log_format &&
3850 curproxy->conf.logformat_string != default_tcp_log_format &&
3851 curproxy->conf.logformat_string != clf_http_log_format)
3852 free(curproxy->conf.logformat_string);
3853 curproxy->conf.logformat_string = default_tcp_log_format;
3854
3855 free(curproxy->conf.lfs_file);
3856 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3857 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 else if (!strcmp(args[1], "tcpka")) {
3860 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003861 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003863
3864 if (curproxy->cap & PR_CAP_FE)
3865 curproxy->options |= PR_O_TCP_CLI_KA;
3866 if (curproxy->cap & PR_CAP_BE)
3867 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003870 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_WARN;
3872
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003874 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003875 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003876 curproxy->options2 &= ~PR_O2_CHK_ANY;
3877 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 if (!*args[2]) { /* no argument */
3879 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3880 curproxy->check_len = strlen(DEF_CHECK_REQ);
3881 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003882 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 curproxy->check_req = (char *)malloc(reqlen);
3884 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003885 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003887 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 if (*args[4])
3889 reqlen += strlen(args[4]);
3890 else
3891 reqlen += strlen("HTTP/1.0");
3892
3893 curproxy->check_req = (char *)malloc(reqlen);
3894 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003895 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003897 }
3898 else if (!strcmp(args[1], "ssl-hello-chk")) {
3899 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003902
Willy Tarreaua534fea2008-08-03 12:19:50 +02003903 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003904 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003905 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003906 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
Willy Tarreau23677902007-05-08 23:50:35 +02003908 else if (!strcmp(args[1], "smtpchk")) {
3909 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003910 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003911 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003912 curproxy->options2 &= ~PR_O2_CHK_ANY;
3913 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003914
3915 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3916 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3917 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3918 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3919 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3920 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3921 curproxy->check_req = (char *)malloc(reqlen);
3922 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3923 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3924 } else {
3925 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3926 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3927 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3928 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3929 }
3930 }
3931 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003932 else if (!strcmp(args[1], "pgsql-check")) {
3933 /* use PostgreSQL request to check servers' health */
3934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3935 err_code |= ERR_WARN;
3936
3937 free(curproxy->check_req);
3938 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003939 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003940 curproxy->options2 |= PR_O2_PGSQL_CHK;
3941
3942 if (*(args[2])) {
3943 int cur_arg = 2;
3944
3945 while (*(args[cur_arg])) {
3946 if (strcmp(args[cur_arg], "user") == 0) {
3947 char * packet;
3948 uint32_t packet_len;
3949 uint32_t pv;
3950
3951 /* suboption header - needs additional argument for it */
3952 if (*(args[cur_arg+1]) == 0) {
3953 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3954 file, linenum, args[0], args[1], args[cur_arg]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958
3959 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3960 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3961 pv = htonl(0x30000); /* protocol version 3.0 */
3962
3963 packet = (char*) calloc(1, packet_len);
3964
3965 memcpy(packet + 4, &pv, 4);
3966
3967 /* copy "user" */
3968 memcpy(packet + 8, "user", 4);
3969
3970 /* copy username */
3971 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3972
3973 free(curproxy->check_req);
3974 curproxy->check_req = packet;
3975 curproxy->check_len = packet_len;
3976
3977 packet_len = htonl(packet_len);
3978 memcpy(packet, &packet_len, 4);
3979 cur_arg += 2;
3980 } else {
3981 /* unknown suboption - catchall */
3982 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3983 file, linenum, args[0], args[1]);
3984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
3986 }
3987 } /* end while loop */
3988 }
3989 }
3990
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003991 else if (!strcmp(args[1], "redis-check")) {
3992 /* use REDIS PING request to check servers' health */
3993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3994 err_code |= ERR_WARN;
3995
3996 free(curproxy->check_req);
3997 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003998 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003999 curproxy->options2 |= PR_O2_REDIS_CHK;
4000
4001 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4002 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4003 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4004 }
4005
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004006 else if (!strcmp(args[1], "mysql-check")) {
4007 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4009 err_code |= ERR_WARN;
4010
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004011 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004012 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004013 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004014 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004015
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004016 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004017 * const char mysql40_client_auth_pkt[] = {
4018 * "\x0e\x00\x00" // packet length
4019 * "\x01" // packet number
4020 * "\x00\x00" // client capabilities
4021 * "\x00\x00\x01" // max packet
4022 * "haproxy\x00" // username (null terminated string)
4023 * "\x00" // filler (always 0x00)
4024 * "\x01\x00\x00" // packet length
4025 * "\x00" // packet number
4026 * "\x01" // COM_QUIT command
4027 * };
4028 */
4029
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004030 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4031 * const char mysql41_client_auth_pkt[] = {
4032 * "\x0e\x00\x00\" // packet length
4033 * "\x01" // packet number
4034 * "\x00\x00\x00\x00" // client capabilities
4035 * "\x00\x00\x00\x01" // max packet
4036 * "\x21" // character set (UTF-8)
4037 * char[23] // All zeroes
4038 * "haproxy\x00" // username (null terminated string)
4039 * "\x00" // filler (always 0x00)
4040 * "\x01\x00\x00" // packet length
4041 * "\x00" // packet number
4042 * "\x01" // COM_QUIT command
4043 * };
4044 */
4045
4046
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004047 if (*(args[2])) {
4048 int cur_arg = 2;
4049
4050 while (*(args[cur_arg])) {
4051 if (strcmp(args[cur_arg], "user") == 0) {
4052 char *mysqluser;
4053 int packetlen, reqlen, userlen;
4054
4055 /* suboption header - needs additional argument for it */
4056 if (*(args[cur_arg+1]) == 0) {
4057 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4058 file, linenum, args[0], args[1], args[cur_arg]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062 mysqluser = args[cur_arg + 1];
4063 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004064
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004065 if (*(args[cur_arg+2])) {
4066 if (!strcmp(args[cur_arg+2], "post-41")) {
4067 packetlen = userlen + 7 + 27;
4068 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004069
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004070 free(curproxy->check_req);
4071 curproxy->check_req = (char *)calloc(1, reqlen);
4072 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004073
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004074 snprintf(curproxy->check_req, 4, "%c%c%c",
4075 ((unsigned char) packetlen & 0xff),
4076 ((unsigned char) (packetlen >> 8) & 0xff),
4077 ((unsigned char) (packetlen >> 16) & 0xff));
4078
4079 curproxy->check_req[3] = 1;
4080 curproxy->check_req[5] = 130;
4081 curproxy->check_req[11] = 1;
4082 curproxy->check_req[12] = 33;
4083 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4084 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4085 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4086 cur_arg += 3;
4087 } else {
4088 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092 } else {
4093 packetlen = userlen + 7;
4094 reqlen = packetlen + 9;
4095
4096 free(curproxy->check_req);
4097 curproxy->check_req = (char *)calloc(1, reqlen);
4098 curproxy->check_len = reqlen;
4099
4100 snprintf(curproxy->check_req, 4, "%c%c%c",
4101 ((unsigned char) packetlen & 0xff),
4102 ((unsigned char) (packetlen >> 8) & 0xff),
4103 ((unsigned char) (packetlen >> 16) & 0xff));
4104
4105 curproxy->check_req[3] = 1;
4106 curproxy->check_req[5] = 128;
4107 curproxy->check_req[8] = 1;
4108 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4109 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4110 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4111 cur_arg += 2;
4112 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004113 } else {
4114 /* unknown suboption - catchall */
4115 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4116 file, linenum, args[0], args[1]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 } /* end while loop */
4121 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004122 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004123 else if (!strcmp(args[1], "ldap-check")) {
4124 /* use LDAP request to check servers' health */
4125 free(curproxy->check_req);
4126 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004127 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004128 curproxy->options2 |= PR_O2_LDAP_CHK;
4129
4130 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4131 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4132 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4133 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004134 else if (!strcmp(args[1], "tcp-check")) {
4135 /* use raw TCPCHK send/expect to check servers' health */
4136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4137 err_code |= ERR_WARN;
4138
4139 free(curproxy->check_req);
4140 curproxy->check_req = NULL;
4141 curproxy->options2 &= ~PR_O2_CHK_ANY;
4142 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4143 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004144 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004145 int cur_arg;
4146
4147 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4148 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004149 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004150
Willy Tarreau87cf5142011-08-19 22:57:24 +02004151 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004152
4153 free(curproxy->fwdfor_hdr_name);
4154 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4155 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4156
4157 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4158 cur_arg = 2;
4159 while (*(args[cur_arg])) {
4160 if (!strcmp(args[cur_arg], "except")) {
4161 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004162 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004163 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4164 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004167 }
4168 /* flush useless bits */
4169 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004170 cur_arg += 2;
4171 } else if (!strcmp(args[cur_arg], "header")) {
4172 /* suboption header - needs additional argument for it */
4173 if (*(args[cur_arg+1]) == 0) {
4174 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4175 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004178 }
4179 free(curproxy->fwdfor_hdr_name);
4180 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4181 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4182 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004183 } else if (!strcmp(args[cur_arg], "if-none")) {
4184 curproxy->options &= ~PR_O_FF_ALWAYS;
4185 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004186 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004187 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004188 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004189 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004192 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004193 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004194 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004195 else if (!strcmp(args[1], "originalto")) {
4196 int cur_arg;
4197
4198 /* insert x-original-to field, but not for the IP address listed as an except.
4199 * set default options (ie: bitfield, header name, etc)
4200 */
4201
4202 curproxy->options |= PR_O_ORGTO;
4203
4204 free(curproxy->orgto_hdr_name);
4205 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4206 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4207
Willy Tarreau87cf5142011-08-19 22:57:24 +02004208 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004209 cur_arg = 2;
4210 while (*(args[cur_arg])) {
4211 if (!strcmp(args[cur_arg], "except")) {
4212 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004213 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 +02004214 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4215 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004218 }
4219 /* flush useless bits */
4220 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4221 cur_arg += 2;
4222 } else if (!strcmp(args[cur_arg], "header")) {
4223 /* suboption header - needs additional argument for it */
4224 if (*(args[cur_arg+1]) == 0) {
4225 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4226 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004229 }
4230 free(curproxy->orgto_hdr_name);
4231 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4232 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4233 cur_arg += 2;
4234 } else {
4235 /* unknown suboption - catchall */
4236 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4237 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004240 }
4241 } /* end while loop */
4242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 else {
4244 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 }
Willy Tarreau93893792009-07-23 13:19:11 +02004248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004250 else if (!strcmp(args[0], "default_backend")) {
4251 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004253
4254 if (*(args[1]) == 0) {
4255 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004258 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004259 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004260 curproxy->defbe.name = strdup(args[1]);
4261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004262 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004265
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004266 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4267 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 +01004268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 /* enable reconnections to dispatch */
4271 curproxy->options |= PR_O_REDISP;
4272 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004273 else if (!strcmp(args[0], "http-check")) {
4274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004276
4277 if (strcmp(args[1], "disable-on-404") == 0) {
4278 /* enable a graceful server shutdown on an HTTP 404 response */
4279 curproxy->options |= PR_O_DISABLE404;
4280 }
Willy Tarreauef781042010-01-27 11:53:01 +01004281 else if (strcmp(args[1], "send-state") == 0) {
4282 /* enable emission of the apparent state of a server in HTTP checks */
4283 curproxy->options2 |= PR_O2_CHK_SNDST;
4284 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004285 else if (strcmp(args[1], "expect") == 0) {
4286 const char *ptr_arg;
4287 int cur_arg;
4288
4289 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4290 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294
4295 cur_arg = 2;
4296 /* consider exclamation marks, sole or at the beginning of a word */
4297 while (*(ptr_arg = args[cur_arg])) {
4298 while (*ptr_arg == '!') {
4299 curproxy->options2 ^= PR_O2_EXP_INV;
4300 ptr_arg++;
4301 }
4302 if (*ptr_arg)
4303 break;
4304 cur_arg++;
4305 }
4306 /* now ptr_arg points to the beginning of a word past any possible
4307 * exclamation mark, and cur_arg is the argument which holds this word.
4308 */
4309 if (strcmp(ptr_arg, "status") == 0) {
4310 if (!*(args[cur_arg + 1])) {
4311 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4312 file, linenum, args[0], args[1], ptr_arg);
4313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
4315 }
4316 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004317 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004318 curproxy->expect_str = strdup(args[cur_arg + 1]);
4319 }
4320 else if (strcmp(ptr_arg, "string") == 0) {
4321 if (!*(args[cur_arg + 1])) {
4322 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4323 file, linenum, args[0], args[1], ptr_arg);
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004328 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004329 curproxy->expect_str = strdup(args[cur_arg + 1]);
4330 }
4331 else if (strcmp(ptr_arg, "rstatus") == 0) {
4332 if (!*(args[cur_arg + 1])) {
4333 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4334 file, linenum, args[0], args[1], ptr_arg);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004339 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004340 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004341 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004342 free(curproxy->expect_regex);
4343 curproxy->expect_regex = NULL;
4344 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004345 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004346 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4347 error = NULL;
4348 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4349 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4350 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4351 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
4354 }
4355 }
4356 else if (strcmp(ptr_arg, "rstring") == 0) {
4357 if (!*(args[cur_arg + 1])) {
4358 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4359 file, linenum, args[0], args[1], ptr_arg);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004364 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004365 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004366 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004367 free(curproxy->expect_regex);
4368 curproxy->expect_regex = NULL;
4369 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004370 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004371 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4372 error = NULL;
4373 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4374 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4375 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4376 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
4379 }
4380 }
4381 else {
4382 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4383 file, linenum, args[0], args[1], ptr_arg);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004388 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004389 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 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004392 }
4393 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004394 else if (!strcmp(args[0], "tcp-check")) {
4395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4396 err_code |= ERR_WARN;
4397
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004398 if (strcmp(args[1], "connect") == 0) {
4399 const char *ptr_arg;
4400 int cur_arg;
4401 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004402
4403 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004404 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004405
Willy Tarreau5bff0592015-05-13 12:24:53 +02004406 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4407 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4408 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4409 file, linenum);
4410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004412 }
4413
4414 cur_arg = 2;
4415 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4416 tcpcheck->action = TCPCHK_ACT_CONNECT;
4417
4418 /* parsing each parameters to fill up the rule */
4419 while (*(ptr_arg = args[cur_arg])) {
4420 /* tcp port */
4421 if (strcmp(args[cur_arg], "port") == 0) {
4422 if ( (atol(args[cur_arg + 1]) > 65535) ||
4423 (atol(args[cur_arg + 1]) < 1) ){
4424 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4425 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429 tcpcheck->port = atol(args[cur_arg + 1]);
4430 cur_arg += 2;
4431 }
4432 /* send proxy protocol */
4433 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4434 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4435 cur_arg++;
4436 }
4437#ifdef USE_OPENSSL
4438 else if (strcmp(args[cur_arg], "ssl") == 0) {
4439 curproxy->options |= PR_O_TCPCHK_SSL;
4440 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4441 cur_arg++;
4442 }
4443#endif /* USE_OPENSSL */
4444 else {
4445#ifdef USE_OPENSSL
4446 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4447#else /* USE_OPENSSL */
4448 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4449#endif /* USE_OPENSSL */
4450 file, linenum, args[0], args[1], args[cur_arg]);
4451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
4454
4455 }
4456
4457 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4458 }
4459 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004460 if (! *(args[2]) ) {
4461 /* SEND string expected */
4462 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4463 file, linenum, args[0], args[1], args[2]);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 } else {
4467 struct tcpcheck_rule *tcpcheck;
4468
4469 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4470
4471 tcpcheck->action = TCPCHK_ACT_SEND;
4472 tcpcheck->string_len = strlen(args[2]);
4473 tcpcheck->string = strdup(args[2]);
4474 tcpcheck->expect_regex = NULL;
4475
4476 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4477 }
4478 }
4479 else if (strcmp(args[1], "send-binary") == 0) {
4480 if (! *(args[2]) ) {
4481 /* SEND binary string expected */
4482 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4483 file, linenum, args[0], args[1], args[2]);
4484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
4486 } else {
4487 struct tcpcheck_rule *tcpcheck;
4488 char *err = NULL;
4489
4490 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4491
4492 tcpcheck->action = TCPCHK_ACT_SEND;
4493 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4494 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4495 file, linenum, args[0], args[1], args[2], err);
4496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
4499 tcpcheck->expect_regex = NULL;
4500
4501 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4502 }
4503 }
4504 else if (strcmp(args[1], "expect") == 0) {
4505 const char *ptr_arg;
4506 int cur_arg;
4507 int inverse = 0;
4508
4509 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4510 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
4514
4515 cur_arg = 2;
4516 /* consider exclamation marks, sole or at the beginning of a word */
4517 while (*(ptr_arg = args[cur_arg])) {
4518 while (*ptr_arg == '!') {
4519 inverse = !inverse;
4520 ptr_arg++;
4521 }
4522 if (*ptr_arg)
4523 break;
4524 cur_arg++;
4525 }
4526 /* now ptr_arg points to the beginning of a word past any possible
4527 * exclamation mark, and cur_arg is the argument which holds this word.
4528 */
4529 if (strcmp(ptr_arg, "binary") == 0) {
4530 if (!*(args[cur_arg + 1])) {
4531 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4532 file, linenum, args[0], args[1], ptr_arg);
4533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
4535 }
4536 struct tcpcheck_rule *tcpcheck;
4537 char *err = NULL;
4538
4539 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4540
4541 tcpcheck->action = TCPCHK_ACT_EXPECT;
4542 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4543 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4544 file, linenum, args[0], args[1], args[2], err);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
4548 tcpcheck->expect_regex = NULL;
4549 tcpcheck->inverse = inverse;
4550
4551 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4552 }
4553 else if (strcmp(ptr_arg, "string") == 0) {
4554 if (!*(args[cur_arg + 1])) {
4555 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4556 file, linenum, args[0], args[1], ptr_arg);
4557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
4559 }
4560 struct tcpcheck_rule *tcpcheck;
4561
4562 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4563
4564 tcpcheck->action = TCPCHK_ACT_EXPECT;
4565 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4566 tcpcheck->string = strdup(args[cur_arg + 1]);
4567 tcpcheck->expect_regex = NULL;
4568 tcpcheck->inverse = inverse;
4569
4570 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4571 }
4572 else if (strcmp(ptr_arg, "rstring") == 0) {
4573 if (!*(args[cur_arg + 1])) {
4574 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4575 file, linenum, args[0], args[1], ptr_arg);
4576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
4578 }
4579 struct tcpcheck_rule *tcpcheck;
4580
4581 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4582
4583 tcpcheck->action = TCPCHK_ACT_EXPECT;
4584 tcpcheck->string_len = 0;
4585 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004586 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4587 error = NULL;
4588 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4589 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4590 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4591 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
4595 tcpcheck->inverse = inverse;
4596
4597 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4598 }
4599 else {
4600 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4601 file, linenum, args[0], args[1], ptr_arg);
4602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
4605 }
4606 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004607 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
4611 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004612 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004613 if (curproxy == &defproxy) {
4614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004617 }
4618
Willy Tarreaub80c2302007-11-30 20:51:32 +01004619 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004621
4622 if (strcmp(args[1], "fail") == 0) {
4623 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004624 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004625 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_ALERT | ERR_FATAL;
4628 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004629 }
4630
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004631 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4632 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4633 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004636 }
4637 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4638 }
4639 else {
4640 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004643 }
4644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645#ifdef TPROXY
4646 else if (!strcmp(args[0], "transparent")) {
4647 /* enable transparent proxy connections */
4648 curproxy->options |= PR_O_TRANSP;
4649 }
4650#endif
4651 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004652 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004654
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 if (*(args[1]) == 0) {
4656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
4660 curproxy->maxconn = atol(args[1]);
4661 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004662 else if (!strcmp(args[0], "backlog")) { /* backlog */
4663 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004664 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004665
4666 if (*(args[1]) == 0) {
4667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004670 }
4671 curproxy->backlog = atol(args[1]);
4672 }
Willy Tarreau86034312006-12-29 00:10:33 +01004673 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004676
Willy Tarreau86034312006-12-29 00:10:33 +01004677 if (*(args[1]) == 0) {
4678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004681 }
4682 curproxy->fullconn = atol(args[1]);
4683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4685 if (*(args[1]) == 0) {
4686 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004690 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4691 if (err) {
4692 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4693 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004696 }
4697 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 }
4699 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004700 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004701 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004702 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004703
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 if (curproxy == &defproxy) {
4705 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004709 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004711
Willy Tarreau902636f2013-03-10 19:44:48 +01004712 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004713 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004714 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004715 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004716 goto out;
4717 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004718
4719 proto = protocol_by_family(sk->ss_family);
4720 if (!proto || !proto->connect) {
4721 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4722 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725 }
4726
4727 if (port1 != port2) {
4728 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4729 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004732 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733
4734 if (!port1) {
4735 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4736 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004740
Willy Tarreaud5191e72010-02-09 20:50:45 +01004741 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004742 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004747
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004748 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4749 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004754 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004755 /**
4756 * The syntax for hash-type config element is
4757 * hash-type {map-based|consistent} [[<algo>] avalanche]
4758 *
4759 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4760 */
4761 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004762
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004763 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4764 err_code |= ERR_WARN;
4765
4766 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004767 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4768 }
4769 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004770 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4771 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004772 else if (strcmp(args[1], "avalanche") == 0) {
4773 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]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004776 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004777 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004778 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781 }
Bhaskar98634f02013-10-29 23:30:51 -04004782
4783 /* set the hash function to use */
4784 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004785 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004786 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004787
4788 /* if consistent with no argument, then avalanche modifier is also applied */
4789 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4790 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004791 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004792 /* set the hash function */
4793 if (!strcmp(args[2], "sdbm")) {
4794 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4795 }
4796 else if (!strcmp(args[2], "djb2")) {
4797 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004798 } else if (!strcmp(args[2], "wt6")) {
4799 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004800 }
4801 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004802 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
4806
4807 /* set the hash modifier */
4808 if (!strcmp(args[3], "avalanche")) {
4809 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4810 }
4811 else if (*args[3]) {
4812 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004816 }
William Lallemanda73203e2012-03-12 12:48:57 +01004817 }
William Lallemanda73203e2012-03-12 12:48:57 +01004818 else if (strcmp(args[0], "unique-id-format") == 0) {
4819 if (!*(args[1])) {
4820 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
William Lallemand3203ff42012-11-11 17:30:56 +01004824 if (*(args[2])) {
4825 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004829 free(curproxy->conf.uniqueid_format_string);
4830 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004831
Willy Tarreau62a61232013-04-12 18:13:46 +02004832 free(curproxy->conf.uif_file);
4833 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4834 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004835 }
William Lallemanda73203e2012-03-12 12:48:57 +01004836
4837 else if (strcmp(args[0], "unique-id-header") == 0) {
4838 if (!*(args[1])) {
4839 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
4843 free(curproxy->header_unique_id);
4844 curproxy->header_unique_id = strdup(args[1]);
4845 }
4846
William Lallemand723b73a2012-02-08 16:37:49 +01004847 else if (strcmp(args[0], "log-format") == 0) {
4848 if (!*(args[1])) {
4849 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
William Lallemand3203ff42012-11-11 17:30:56 +01004853 if (*(args[2])) {
4854 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
4857 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004858
Willy Tarreau62a61232013-04-12 18:13:46 +02004859 if (curproxy->conf.logformat_string != default_http_log_format &&
4860 curproxy->conf.logformat_string != default_tcp_log_format &&
4861 curproxy->conf.logformat_string != clf_http_log_format)
4862 free(curproxy->conf.logformat_string);
4863 curproxy->conf.logformat_string = strdup(args[1]);
4864
4865 free(curproxy->conf.lfs_file);
4866 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4867 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004868
4869 /* get a chance to improve log-format error reporting by
4870 * reporting the correct line-number when possible.
4871 */
4872 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4873 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4874 file, linenum, curproxy->id);
4875 err_code |= ERR_WARN;
4876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
William Lallemand723b73a2012-02-08 16:37:49 +01004878
William Lallemand0f99e342011-10-12 17:50:54 +02004879 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4880 /* delete previous herited or defined syslog servers */
4881 struct logsrv *back;
4882
4883 if (*(args[1]) != 0) {
4884 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888
William Lallemand723b73a2012-02-08 16:37:49 +01004889 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4890 LIST_DEL(&tmplogsrv->list);
4891 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004892 }
4893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004895 struct logsrv *logsrv;
4896
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004898 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004899 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004900 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004901 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004902 LIST_INIT(&node->list);
4903 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
4906 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004907 struct sockaddr_storage *sk;
4908 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004909 int arg = 0;
4910 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004911
4912 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004914 /* just after the address, a length may be specified */
4915 if (strcmp(args[arg+2], "len") == 0) {
4916 len = atoi(args[arg+3]);
4917 if (len < 80 || len > 65535) {
4918 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4919 file, linenum, args[arg+3]);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923 logsrv->maxlen = len;
4924
4925 /* skip these two args */
4926 arg += 2;
4927 }
4928 else
4929 logsrv->maxlen = MAX_SYSLOG_LEN;
4930
4931 if (logsrv->maxlen > global.max_syslog_len) {
4932 global.max_syslog_len = logsrv->maxlen;
4933 logline = realloc(logline, global.max_syslog_len + 1);
4934 }
4935
4936 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004937 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004938 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
4941
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
4943
William Lallemand0f99e342011-10-12 17:50:54 +02004944 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004945 if (*(args[arg+3])) {
4946 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004947 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004948 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 }
4954
William Lallemand0f99e342011-10-12 17:50:54 +02004955 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004956 if (*(args[arg+4])) {
4957 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004958 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004959 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
4962
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004963 }
4964 }
4965
Willy Tarreau902636f2013-03-10 19:44:48 +01004966 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004967 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004968 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004970 goto out;
4971 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004972
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004973 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004974
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004975 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004976 if (port1 != port2) {
4977 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4978 file, linenum, args[0], args[1]);
4979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
4981 }
4982
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004983 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004984 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
William Lallemand0f99e342011-10-12 17:50:54 +02004986
4987 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 else {
4990 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4991 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 }
4996 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004997 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004998 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004999 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005000 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005001
Willy Tarreau977b8e42006-12-29 14:19:17 +01005002 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005006 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5007 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005011
5012 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005013 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5014 free(curproxy->conn_src.iface_name);
5015 curproxy->conn_src.iface_name = NULL;
5016 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005017
Willy Tarreau902636f2013-03-10 19:44:48 +01005018 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005019 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005020 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005021 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005023 goto out;
5024 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005025
5026 proto = protocol_by_family(sk->ss_family);
5027 if (!proto || !proto->connect) {
5028 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005029 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005033
5034 if (port1 != port2) {
5035 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5036 file, linenum, args[0], args[1]);
5037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039 }
5040
Willy Tarreauef9a3602012-12-08 22:29:20 +01005041 curproxy->conn_src.source_addr = *sk;
5042 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005043
5044 cur_arg = 2;
5045 while (*(args[cur_arg])) {
5046 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005047#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5048#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005049 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005050 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5051 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005054 }
5055#endif
5056 if (!*args[cur_arg + 1]) {
5057 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5058 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005061 }
5062
5063 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005064 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5065 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005067 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5068 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005069 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5070 char *name, *end;
5071
5072 name = args[cur_arg+1] + 7;
5073 while (isspace(*name))
5074 name++;
5075
5076 end = name;
5077 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5078 end++;
5079
Willy Tarreauef9a3602012-12-08 22:29:20 +01005080 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5081 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5082 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5083 curproxy->conn_src.bind_hdr_len = end - name;
5084 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5085 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5086 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005087
5088 /* now look for an occurrence number */
5089 while (isspace(*end))
5090 end++;
5091 if (*end == ',') {
5092 end++;
5093 name = end;
5094 if (*end == '-')
5095 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005096 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005097 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005098 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005099 }
5100
Willy Tarreauef9a3602012-12-08 22:29:20 +01005101 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005102 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5103 " occurrences values smaller than %d.\n",
5104 file, linenum, MAX_HDR_HISTORY);
5105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
5107 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005108 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005109 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005110
Willy Tarreau902636f2013-03-10 19:44:48 +01005111 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005112 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005113 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005114 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005115 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005116 goto out;
5117 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005118
5119 proto = protocol_by_family(sk->ss_family);
5120 if (!proto || !proto->connect) {
5121 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5122 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
5125 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005126
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005127 if (port1 != port2) {
5128 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5129 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
5132 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005133 curproxy->conn_src.tproxy_addr = *sk;
5134 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005135 }
5136 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005137#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005138 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005139#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005140#else /* no TPROXY support */
5141 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005142 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005145#endif
5146 cur_arg += 2;
5147 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005148 }
5149
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005150 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5151#ifdef SO_BINDTODEVICE
5152 if (!*args[cur_arg + 1]) {
5153 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005157 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005158 free(curproxy->conn_src.iface_name);
5159 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5160 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005161 global.last_checks |= LSTCHK_NETADM;
5162#else
5163 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5164 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005167#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005168 cur_arg += 2;
5169 continue;
5170 }
5171 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005172 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005177 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5178 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5179 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190
5191 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005192 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005193 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
5197 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005198 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005199 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005200 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
5204 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005205 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005206 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005207 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005213 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005214 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
5218 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005219 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005220 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005221 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005225 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005227 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005228 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005230 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005231 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005232 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005234 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005235 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005237 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005238
5239 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5240 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005241 }
5242 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005244 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005245 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005247 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005248
5249 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5250 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259
5260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005262 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
5266 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
5280 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005294 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005302 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 if (curproxy == &defproxy) {
5305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005309 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 if (*(args[1]) == 0) {
5313 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005317
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005318 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005319 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5320 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5321 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005325 err_code |= warnif_cond_conflicts(cond,
5326 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5327 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005328 }
5329 else if (*args[2]) {
5330 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5331 file, linenum, args[0], args[2]);
5332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
5335
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005336 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005337 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005338 wl->s = strdup(args[1]);
5339 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005340 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
5342 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005349
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005351 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005352 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
5356 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005358 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005365 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005371 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
5377
Willy Tarreauade5ec42010-01-28 19:33:49 +01005378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005379 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005380 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005386 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005393 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005394 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 }
5398 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005399 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005400
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 if (curproxy == &defproxy) {
5402 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005406 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 if (*(args[1]) == 0) {
5410 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
5414
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005415 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005416 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5417 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5418 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005422 err_code |= warnif_cond_conflicts(cond,
5423 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5424 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005425 }
5426 else if (*args[2]) {
5427 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5428 file, linenum, args[0], args[2]);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005433 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005434 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005435 wl->s = strdup(args[1]);
5436 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 }
5438 else if (!strcmp(args[0], "errorloc") ||
5439 !strcmp(args[0], "errorloc302") ||
5440 !strcmp(args[0], "errorloc303")) { /* error location */
5441 int errnum, errlen;
5442 char *err;
5443
Willy Tarreau977b8e42006-12-29 14:19:17 +01005444 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005446
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005448 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005451 }
5452
5453 errnum = atol(args[1]);
5454 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005455 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5456 err = malloc(errlen);
5457 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005459 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5460 err = malloc(errlen);
5461 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 }
5463
Willy Tarreau0f772532006-12-23 20:51:41 +01005464 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5465 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005466 chunk_destroy(&curproxy->errmsg[rc]);
5467 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005468 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005471
5472 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005473 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
5474 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 free(err);
5476 }
5477 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005478 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5479 int errnum, errlen, fd;
5480 char *err;
5481 struct stat stat;
5482
5483 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005484 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005485
5486 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005487 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005490 }
5491
5492 fd = open(args[2], O_RDONLY);
5493 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5494 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5495 file, linenum, args[2], args[1]);
5496 if (fd >= 0)
5497 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501
Willy Tarreau27a674e2009-08-17 07:23:33 +02005502 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005503 errlen = stat.st_size;
5504 } else {
5505 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005506 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005508 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005509 }
5510
5511 err = malloc(errlen); /* malloc() must succeed during parsing */
5512 errnum = read(fd, err, errlen);
5513 if (errnum != errlen) {
5514 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5515 file, linenum, args[2], args[1]);
5516 close(fd);
5517 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005520 }
5521 close(fd);
5522
5523 errnum = atol(args[1]);
5524 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5525 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005526 chunk_destroy(&curproxy->errmsg[rc]);
5527 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005528 break;
5529 }
5530 }
5531
5532 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005533 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
5534 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005535 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005536 free(err);
5537 }
5538 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005539 else if (!strcmp(args[0], "compression")) {
5540 struct comp *comp;
5541 if (curproxy->comp == NULL) {
5542 comp = calloc(1, sizeof(struct comp));
5543 curproxy->comp = comp;
5544 } else {
5545 comp = curproxy->comp;
5546 }
5547
5548 if (!strcmp(args[1], "algo")) {
5549 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005550 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005551
William Lallemand82fe75c2012-10-23 10:25:10 +02005552 cur_arg = 2;
5553 if (!*args[cur_arg]) {
5554 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5555 file, linenum, args[0]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559 while (*(args[cur_arg])) {
5560 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5561 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5562 file, linenum, args[0], args[cur_arg]);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
William Lallemand552df672012-11-07 13:21:47 +01005566 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5567 curproxy->comp->algos->end(&ctx);
5568 } else {
5569 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5570 file, linenum, args[0], args[cur_arg]);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005574 cur_arg ++;
5575 continue;
5576 }
5577 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005578 else if (!strcmp(args[1], "offload")) {
5579 comp->offload = 1;
5580 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005581 else if (!strcmp(args[1], "type")) {
5582 int cur_arg;
5583 cur_arg = 2;
5584 if (!*args[cur_arg]) {
5585 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5586 file, linenum, args[0]);
5587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
5589 }
5590 while (*(args[cur_arg])) {
5591 comp_append_type(comp, args[cur_arg]);
5592 cur_arg ++;
5593 continue;
5594 }
5595 }
5596 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005597 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005598 file, linenum, args[0]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005604 struct cfg_kw_list *kwl;
5605 int index;
5606
5607 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5608 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5609 if (kwl->kw[index].section != CFG_LISTEN)
5610 continue;
5611 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5612 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005613 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005614 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005615 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005618 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005619 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005620 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005621 err_code |= ERR_WARN;
5622 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005623 }
Willy Tarreau93893792009-07-23 13:19:11 +02005624 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005625 }
5626 }
5627 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005628
Willy Tarreau6daf3432008-01-22 16:44:08 +01005629 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 }
Willy Tarreau93893792009-07-23 13:19:11 +02005633 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005634 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005635 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636}
5637
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005638int
5639cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5640{
5641
5642 int err_code = 0;
5643 const char *err;
5644
5645 if (!strcmp(args[0], "userlist")) { /* new userlist */
5646 struct userlist *newul;
5647
5648 if (!*args[1]) {
5649 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5650 file, linenum, args[0]);
5651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
5653 }
5654
5655 err = invalid_char(args[1]);
5656 if (err) {
5657 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5658 file, linenum, *err, args[0], args[1]);
5659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
5662
5663 for (newul = userlist; newul; newul = newul->next)
5664 if (!strcmp(newul->name, args[1])) {
5665 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5666 file, linenum, args[1]);
5667 err_code |= ERR_WARN;
5668 goto out;
5669 }
5670
5671 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5672 if (!newul) {
5673 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5674 err_code |= ERR_ALERT | ERR_ABORT;
5675 goto out;
5676 }
5677
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005678 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005679 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005680 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5681 err_code |= ERR_ALERT | ERR_ABORT;
5682 goto out;
5683 }
5684
5685 newul->next = userlist;
5686 userlist = newul;
5687
5688 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005689 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005690 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005691 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005692
5693 if (!*args[1]) {
5694 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5695 file, linenum, args[0]);
5696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
5698 }
5699
5700 err = invalid_char(args[1]);
5701 if (err) {
5702 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5703 file, linenum, *err, args[0], args[1]);
5704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
5706 }
5707
William Lallemandfaf33152015-05-28 18:03:51 +02005708 if (!userlist)
5709 goto out;
5710
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005711 for (ag = userlist->groups; ag; ag = ag->next)
5712 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005713 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5714 file, linenum, args[1], userlist->name);
5715 err_code |= ERR_ALERT;
5716 goto out;
5717 }
5718
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005719 ag = calloc(1, sizeof(*ag));
5720 if (!ag) {
5721 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5722 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005723 goto out;
5724 }
5725
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005726 ag->name = strdup(args[1]);
5727 if (!ag) {
5728 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5729 err_code |= ERR_ALERT | ERR_ABORT;
5730 goto out;
5731 }
5732
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005733 cur_arg = 2;
5734
5735 while (*args[cur_arg]) {
5736 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005737 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005738 cur_arg += 2;
5739 continue;
5740 } else {
5741 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5742 file, linenum, args[0]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746 }
5747
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005748 ag->next = userlist->groups;
5749 userlist->groups = ag;
5750
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005751 } else if (!strcmp(args[0], "user")) { /* new user */
5752 struct auth_users *newuser;
5753 int cur_arg;
5754
5755 if (!*args[1]) {
5756 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5757 file, linenum, args[0]);
5758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
William Lallemandfaf33152015-05-28 18:03:51 +02005761 if (!userlist)
5762 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005763
5764 for (newuser = userlist->users; newuser; newuser = newuser->next)
5765 if (!strcmp(newuser->user, args[1])) {
5766 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5767 file, linenum, args[1], userlist->name);
5768 err_code |= ERR_ALERT;
5769 goto out;
5770 }
5771
5772 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5773 if (!newuser) {
5774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5775 err_code |= ERR_ALERT | ERR_ABORT;
5776 goto out;
5777 }
5778
5779 newuser->user = strdup(args[1]);
5780
5781 newuser->next = userlist->users;
5782 userlist->users = newuser;
5783
5784 cur_arg = 2;
5785
5786 while (*args[cur_arg]) {
5787 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005788#ifdef CONFIG_HAP_CRYPT
5789 if (!crypt("", args[cur_arg + 1])) {
5790 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5791 file, linenum, newuser->user);
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
5794 }
5795#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005796 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5797 file, linenum);
5798 err_code |= ERR_ALERT;
5799#endif
5800 newuser->pass = strdup(args[cur_arg + 1]);
5801 cur_arg += 2;
5802 continue;
5803 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5804 newuser->pass = strdup(args[cur_arg + 1]);
5805 newuser->flags |= AU_O_INSECURE;
5806 cur_arg += 2;
5807 continue;
5808 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005809 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005810 cur_arg += 2;
5811 continue;
5812 } else {
5813 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5814 file, linenum, args[0]);
5815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817 }
5818 }
5819 } else {
5820 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5821 err_code |= ERR_ALERT | ERR_FATAL;
5822 }
5823
5824out:
5825 return err_code;
5826}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827
5828/*
5829 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005830 * Returns the error code, 0 if OK, or any combination of :
5831 * - ERR_ABORT: must abort ASAP
5832 * - ERR_FATAL: we can continue parsing but not start the service
5833 * - ERR_WARN: a warning has been emitted
5834 * - ERR_ALERT: an alert has been emitted
5835 * Only the two first ones can stop processing, the two others are just
5836 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005838int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005840 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 FILE *f;
5842 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005843 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005844 struct cfg_section *cs = NULL;
5845 struct cfg_section *ics;
5846
5847 /* Register internal sections */
5848 if (!cfg_register_section("listen", cfg_parse_listen) ||
5849 !cfg_register_section("frontend", cfg_parse_listen) ||
5850 !cfg_register_section("backend", cfg_parse_listen) ||
5851 !cfg_register_section("ruleset", cfg_parse_listen) ||
5852 !cfg_register_section("defaults", cfg_parse_listen) ||
5853 !cfg_register_section("global", cfg_parse_global) ||
5854 !cfg_register_section("userlist", cfg_parse_users) ||
5855 !cfg_register_section("peers", cfg_parse_peers))
5856 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857
Willy Tarreaubaaee002006-06-26 02:48:02 +02005858 if ((f=fopen(file,"r")) == NULL)
5859 return -1;
5860
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005861 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005862 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005863 char *end;
5864 char *args[MAX_LINE_ARGS + 1];
5865 char *line = thisline;
5866
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 linenum++;
5868
5869 end = line + strlen(line);
5870
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005871 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5872 /* Check if we reached the limit and the last char is not \n.
5873 * Watch out for the last line without the terminating '\n'!
5874 */
5875 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005876 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005877 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005878 }
5879
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005881 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 line++;
5883
5884 arg = 0;
5885 args[arg] = line;
5886
5887 while (*line && arg < MAX_LINE_ARGS) {
5888 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5889 * C equivalent value. Other combinations left unchanged (eg: \1).
5890 */
5891 if (*line == '\\') {
5892 int skip = 0;
5893 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5894 *line = line[1];
5895 skip = 1;
5896 }
5897 else if (line[1] == 'r') {
5898 *line = '\r';
5899 skip = 1;
5900 }
5901 else if (line[1] == 'n') {
5902 *line = '\n';
5903 skip = 1;
5904 }
5905 else if (line[1] == 't') {
5906 *line = '\t';
5907 skip = 1;
5908 }
5909 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005910 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 unsigned char hex1, hex2;
5912 hex1 = toupper(line[2]) - '0';
5913 hex2 = toupper(line[3]) - '0';
5914 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5915 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5916 *line = (hex1<<4) + hex2;
5917 skip = 3;
5918 }
5919 else {
5920 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005921 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
5923 }
5924 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005925 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 end -= skip;
5927 }
5928 line++;
5929 }
5930 else if (*line == '#' || *line == '\n' || *line == '\r') {
5931 /* end of string, end of loop */
5932 *line = 0;
5933 break;
5934 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005935 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005937 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005938 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939 line++;
5940 args[++arg] = line;
5941 }
5942 else {
5943 line++;
5944 }
5945 }
5946
5947 /* empty line */
5948 if (!**args)
5949 continue;
5950
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005951 if (*line) {
5952 /* we had to stop due to too many args.
5953 * Let's terminate the string, print the offending part then cut the
5954 * last arg.
5955 */
5956 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5957 line++;
5958 *line = '\0';
5959
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005960 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005961 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005962 err_code |= ERR_ALERT | ERR_FATAL;
5963 args[arg] = line;
5964 }
5965
Willy Tarreau540abe42007-05-02 20:50:16 +02005966 /* zero out remaining args and ensure that at least one entry
5967 * is zeroed out.
5968 */
5969 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 args[arg] = line;
5971 }
5972
Willy Tarreau3842f002009-06-14 11:39:52 +02005973 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005974 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005975 char *tmp;
5976
Willy Tarreau3842f002009-06-14 11:39:52 +02005977 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005978 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005979 for (arg=0; *args[arg+1]; arg++)
5980 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005981 *tmp = '\0'; // fix the next arg to \0
5982 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005983 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005984 else if (!strcmp(args[0], "default")) {
5985 kwm = KWM_DEF;
5986 for (arg=0; *args[arg+1]; arg++)
5987 args[arg] = args[arg+1]; // shift args after inversion
5988 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005989
William Lallemand0f99e342011-10-12 17:50:54 +02005990 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5991 strcmp(args[0], "log") != 0) {
5992 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005993 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005994 }
5995
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005996 /* detect section start */
5997 list_for_each_entry(ics, &sections, list) {
5998 if (strcmp(args[0], ics->section_name) == 0) {
5999 cursection = ics->section_name;
6000 cs = ics;
6001 break;
6002 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006003 }
6004
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006006 if (cs)
6007 err_code |= cs->section_parser(file, linenum, args, kwm);
6008 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006009 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006010 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006012
6013 if (err_code & ERR_ABORT)
6014 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006016 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006018 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006019}
6020
Willy Tarreau5436afc2014-09-16 12:17:36 +02006021/* This function propagates processes from frontend <from> to backend <to> so
6022 * that it is always guaranteed that a backend pointed to by a frontend is
6023 * bound to all of its processes. After that, if the target is a "listen"
6024 * instance, the function recursively descends the target's own targets along
6025 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6026 * checked first to ensure that <to> is already bound to all processes of
6027 * <from>, there is no risk of looping and we ensure to follow the shortest
6028 * path to the destination.
6029 *
6030 * It is possible to set <to> to NULL for the first call so that the function
6031 * takes care of visiting the initial frontend in <from>.
6032 *
6033 * It is important to note that the function relies on the fact that all names
6034 * have already been resolved.
6035 */
6036void propagate_processes(struct proxy *from, struct proxy *to)
6037{
6038 struct switching_rule *rule;
6039 struct hdr_exp *exp;
6040
6041 if (to) {
6042 /* check whether we need to go down */
6043 if (from->bind_proc &&
6044 (from->bind_proc & to->bind_proc) == from->bind_proc)
6045 return;
6046
6047 if (!from->bind_proc && !to->bind_proc)
6048 return;
6049
6050 to->bind_proc = from->bind_proc ?
6051 (to->bind_proc | from->bind_proc) : 0;
6052
6053 /* now propagate down */
6054 from = to;
6055 }
6056
Willy Tarreau7110f382014-12-18 13:56:26 +01006057 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006058 return;
6059
Willy Tarreaued061c02014-12-18 14:00:43 +01006060 if (from->state == PR_STSTOPPED)
6061 return;
6062
Willy Tarreau5436afc2014-09-16 12:17:36 +02006063 /* default_backend */
6064 if (from->defbe.be)
6065 propagate_processes(from, from->defbe.be);
6066
6067 /* use_backend */
6068 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006069 if (rule->dynamic)
6070 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006071 to = rule->be.backend;
6072 propagate_processes(from, to);
6073 }
6074
6075 /* reqsetbe */
6076 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6077 if (exp->action != ACT_SETBE)
6078 continue;
6079 to = (struct proxy *)exp->replace;
6080 propagate_processes(from, to);
6081 }
6082}
6083
Willy Tarreaubb925012009-07-23 13:36:36 +02006084/*
6085 * Returns the error code, 0 if OK, or any combination of :
6086 * - ERR_ABORT: must abort ASAP
6087 * - ERR_FATAL: we can continue parsing but not start the service
6088 * - ERR_WARN: a warning has been emitted
6089 * - ERR_ALERT: an alert has been emitted
6090 * Only the two first ones can stop processing, the two others are just
6091 * indicators.
6092 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006093int check_config_validity()
6094{
6095 int cfgerr = 0;
6096 struct proxy *curproxy = NULL;
6097 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006098 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006099 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006100 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006102 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 /*
6104 * Now, check for the integrity of all that we have collected.
6105 */
6106
6107 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006108 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109
Willy Tarreau193b8c62012-11-22 00:17:38 +01006110 if (!global.tune.max_http_hdr)
6111 global.tune.max_http_hdr = MAX_HTTP_HDR;
6112
6113 if (!global.tune.cookie_len)
6114 global.tune.cookie_len = CAPTURE_LEN;
6115
6116 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6117
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006118 /* Post initialisation of the users and groups lists. */
6119 err_code = userlist_postinit();
6120 if (err_code != ERR_NONE)
6121 goto out;
6122
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006123 /* first, we will invert the proxy list order */
6124 curproxy = NULL;
6125 while (proxy) {
6126 struct proxy *next;
6127
6128 next = proxy->next;
6129 proxy->next = curproxy;
6130 curproxy = proxy;
6131 if (!next)
6132 break;
6133 proxy = next;
6134 }
6135
Willy Tarreau91b00c22014-09-16 13:41:21 +02006136 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006137 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006138 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006139 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006140 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006141 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006142 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006143
Willy Tarreau050536d2012-10-04 08:47:34 +02006144 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006145 /* proxy ID not set, use automatic numbering with first
6146 * spare entry starting with next_pxid.
6147 */
6148 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6149 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6150 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006151 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006152 next_pxid++;
6153
Willy Tarreau55ea7572007-06-17 19:56:27 +02006154
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006156 /* ensure we don't keep listeners uselessly bound */
6157 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006158 free((void *)curproxy->table.peers.name);
6159 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 continue;
6161 }
6162
Willy Tarreau102df612014-05-07 23:56:38 +02006163 /* Check multi-process mode compatibility for the current proxy */
6164
6165 if (curproxy->bind_proc) {
6166 /* an explicit bind-process was specified, let's check how many
6167 * processes remain.
6168 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006169 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006170
6171 curproxy->bind_proc &= nbits(global.nbproc);
6172 if (!curproxy->bind_proc && nbproc == 1) {
6173 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);
6174 curproxy->bind_proc = 1;
6175 }
6176 else if (!curproxy->bind_proc && nbproc > 1) {
6177 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);
6178 curproxy->bind_proc = 0;
6179 }
6180 }
6181
Willy Tarreau3d209582014-05-09 17:06:11 +02006182 /* check and reduce the bind-proc of each listener */
6183 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6184 unsigned long mask;
6185
6186 if (!bind_conf->bind_proc)
6187 continue;
6188
6189 mask = nbits(global.nbproc);
6190 if (curproxy->bind_proc)
6191 mask &= curproxy->bind_proc;
6192 /* mask cannot be null here thanks to the previous checks */
6193
David Carlier6de4c2f2015-07-02 07:00:17 +00006194 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006195 bind_conf->bind_proc &= mask;
6196
6197 if (!bind_conf->bind_proc && nbproc == 1) {
6198 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",
6199 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6200 bind_conf->bind_proc = mask & ~(mask - 1);
6201 }
6202 else if (!bind_conf->bind_proc && nbproc > 1) {
6203 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",
6204 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6205 bind_conf->bind_proc = 0;
6206 }
6207 }
6208
Willy Tarreauff01a212009-03-15 13:46:16 +01006209 switch (curproxy->mode) {
6210 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006212 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006213 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6214 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006215 cfgerr++;
6216 }
6217
6218 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006219 Warning("config : servers will be ignored for %s '%s'.\n",
6220 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006221 break;
6222
6223 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006224 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006225 break;
6226
6227 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006228 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006229 break;
6230 }
6231
Willy Tarreauc7c1e552015-08-11 11:36:45 +02006232 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
6233 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
6234 proxy_type_str(curproxy), curproxy->id);
6235 err_code |= ERR_WARN;
6236 }
6237
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006238 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006239 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006240 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006241 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6242 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006243 cfgerr++;
6244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006246 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6248 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006249 cfgerr++;
6250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006252 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006253 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6254 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006255 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006256 }
6257 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006258 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006259 /* If no LB algo is set in a backend, and we're not in
6260 * transparent mode, dispatch mode nor proxy mode, we
6261 * want to use balance roundrobin by default.
6262 */
6263 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6264 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
6266 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006267
Willy Tarreau1620ec32011-08-06 17:05:02 +02006268 if (curproxy->options & PR_O_DISPATCH)
6269 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6270 else if (curproxy->options & PR_O_HTTP_PROXY)
6271 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6272 else if (curproxy->options & PR_O_TRANSP)
6273 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006274
Willy Tarreau1620ec32011-08-06 17:05:02 +02006275 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6276 if (curproxy->options & PR_O_DISABLE404) {
6277 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6278 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6279 err_code |= ERR_WARN;
6280 curproxy->options &= ~PR_O_DISABLE404;
6281 }
6282 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6283 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6284 "send-state", proxy_type_str(curproxy), curproxy->id);
6285 err_code |= ERR_WARN;
6286 curproxy->options &= ~PR_O2_CHK_SNDST;
6287 }
Willy Tarreauef781042010-01-27 11:53:01 +01006288 }
6289
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006290 /* if a default backend was specified, let's find it */
6291 if (curproxy->defbe.name) {
6292 struct proxy *target;
6293
Alex Williams96532db2009-11-01 21:27:13 -05006294 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006295 if (!target) {
6296 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6297 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006298 cfgerr++;
6299 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006300 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6301 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006302 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006303 } else {
6304 free(curproxy->defbe.name);
6305 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006306
6307 /* Emit a warning if this proxy also has some servers */
6308 if (curproxy->srv) {
6309 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6310 curproxy->id);
6311 err_code |= ERR_WARN;
6312 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 }
6314 }
6315
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006316 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006317 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6318 /* map jump target for ACT_SETBE in req_rep chain */
6319 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006320 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006321 struct proxy *target;
6322
Willy Tarreaua496b602006-12-17 23:15:24 +01006323 if (exp->action != ACT_SETBE)
6324 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006325
Alex Williams96532db2009-11-01 21:27:13 -05006326 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006327 if (!target) {
6328 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6329 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006330 cfgerr++;
6331 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006332 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6333 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006334 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006335 } else {
6336 free((void *)exp->replace);
6337 exp->replace = (const char *)target;
6338 }
6339 }
6340 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006341
6342 /* find the target proxy for 'use_backend' rules */
6343 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006344 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006345 struct logformat_node *node;
6346 char *pxname;
6347
6348 /* Try to parse the string as a log format expression. If the result
6349 * of the parsing is only one entry containing a simple string, then
6350 * it's a standard string corresponding to a static rule, thus the
6351 * parsing is cancelled and be.name is restored to be resolved.
6352 */
6353 pxname = rule->be.name;
6354 LIST_INIT(&rule->be.expr);
6355 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6356 curproxy->conf.args.file, curproxy->conf.args.line);
6357 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6358
6359 if (!LIST_ISEMPTY(&rule->be.expr)) {
6360 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6361 rule->dynamic = 1;
6362 free(pxname);
6363 continue;
6364 }
6365 /* simple string: free the expression and fall back to static rule */
6366 free(node->arg);
6367 free(node);
6368 }
6369
6370 rule->dynamic = 0;
6371 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006372
Alex Williams96532db2009-11-01 21:27:13 -05006373 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006374
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006375 if (!target) {
6376 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6377 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006378 cfgerr++;
6379 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006380 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6381 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006382 cfgerr++;
6383 } else {
6384 free((void *)rule->be.name);
6385 rule->be.backend = target;
6386 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006387 }
6388
Willy Tarreau5436afc2014-09-16 12:17:36 +02006389 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006390 list_for_each_entry(srule, &curproxy->server_rules, list) {
6391 struct server *target = findserver(curproxy, srule->srv.name);
6392
6393 if (!target) {
6394 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6395 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6396 cfgerr++;
6397 continue;
6398 }
6399 free((void *)srule->srv.name);
6400 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006401 }
6402
Emeric Brunb982a3d2010-01-04 15:45:53 +01006403 /* find the target table for 'stick' rules */
6404 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6405 struct proxy *target;
6406
Emeric Brun1d33b292010-01-04 15:47:17 +01006407 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6408 if (mrule->flags & STK_IS_STORE)
6409 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6410
Emeric Brunb982a3d2010-01-04 15:45:53 +01006411 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006412 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006413 else
6414 target = curproxy;
6415
6416 if (!target) {
6417 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6418 curproxy->id, mrule->table.name);
6419 cfgerr++;
6420 }
6421 else if (target->table.size == 0) {
6422 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6423 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6424 cfgerr++;
6425 }
Willy Tarreau12785782012-04-27 21:37:17 +02006426 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6427 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006428 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6429 cfgerr++;
6430 }
6431 else {
6432 free((void *)mrule->table.name);
6433 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006434 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006435 }
6436 }
6437
6438 /* find the target table for 'store response' rules */
6439 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6440 struct proxy *target;
6441
Emeric Brun1d33b292010-01-04 15:47:17 +01006442 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6443
Emeric Brunb982a3d2010-01-04 15:45:53 +01006444 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006445 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006446 else
6447 target = curproxy;
6448
6449 if (!target) {
6450 Alert("Proxy '%s': unable to find store table '%s'.\n",
6451 curproxy->id, mrule->table.name);
6452 cfgerr++;
6453 }
6454 else if (target->table.size == 0) {
6455 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6456 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6457 cfgerr++;
6458 }
Willy Tarreau12785782012-04-27 21:37:17 +02006459 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6460 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006461 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6462 cfgerr++;
6463 }
6464 else {
6465 free((void *)mrule->table.name);
6466 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006467 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006468 }
6469 }
6470
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006471 /* find the target table for 'tcp-request' layer 4 rules */
6472 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6473 struct proxy *target;
6474
Willy Tarreaub4c84932013-07-23 19:15:30 +02006475 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006476 continue;
6477
6478 if (trule->act_prm.trk_ctr.table.n)
6479 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6480 else
6481 target = curproxy;
6482
6483 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006484 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6485 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006486 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006487 cfgerr++;
6488 }
6489 else if (target->table.size == 0) {
6490 Alert("Proxy '%s': table '%s' used but not configured.\n",
6491 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6492 cfgerr++;
6493 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006494 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6495 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6496 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006497 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006498 cfgerr++;
6499 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006500 else {
6501 free(trule->act_prm.trk_ctr.table.n);
6502 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006503 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006504 * to pass a list of counters to track and allocate them right here using
6505 * stktable_alloc_data_type().
6506 */
6507 }
6508 }
6509
Willy Tarreaud1f96522010-08-03 19:34:32 +02006510 /* find the target table for 'tcp-request' layer 6 rules */
6511 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6512 struct proxy *target;
6513
Willy Tarreaub4c84932013-07-23 19:15:30 +02006514 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006515 continue;
6516
6517 if (trule->act_prm.trk_ctr.table.n)
6518 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6519 else
6520 target = curproxy;
6521
6522 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006523 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6524 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006525 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006526 cfgerr++;
6527 }
6528 else if (target->table.size == 0) {
6529 Alert("Proxy '%s': table '%s' used but not configured.\n",
6530 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6531 cfgerr++;
6532 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006533 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6534 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6535 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006536 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006537 cfgerr++;
6538 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006539 else {
6540 free(trule->act_prm.trk_ctr.table.n);
6541 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006542 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006543 * to pass a list of counters to track and allocate them right here using
6544 * stktable_alloc_data_type().
6545 */
6546 }
6547 }
6548
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006549 /* move any "block" rules at the beginning of the http-request rules */
6550 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6551 /* insert block_rules into http_req_rules at the beginning */
6552 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6553 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6554 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6555 curproxy->http_req_rules.n = curproxy->block_rules.n;
6556 LIST_INIT(&curproxy->block_rules);
6557 }
6558
Emeric Brun32da3c42010-09-23 18:39:19 +02006559 if (curproxy->table.peers.name) {
6560 struct peers *curpeers = peers;
6561
6562 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6563 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6564 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006565 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006566 break;
6567 }
6568 }
6569
6570 if (!curpeers) {
6571 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6572 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006573 free((void *)curproxy->table.peers.name);
6574 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006575 cfgerr++;
6576 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006577 else if (curpeers->state == PR_STSTOPPED) {
6578 /* silently disable this peers section */
6579 curproxy->table.peers.p = NULL;
6580 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006581 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006582 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6583 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006584 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006585 cfgerr++;
6586 }
6587 }
6588
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006589 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006590 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006591 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6592 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6593 "proxy", curproxy->id);
6594 cfgerr++;
6595 goto out_uri_auth_compat;
6596 }
6597
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006598 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006599 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006600 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006601 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006602
Willy Tarreau95fa4692010-02-01 13:05:50 +01006603 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6604 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006605
6606 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006607 uri_auth_compat_req[i++] = "realm";
6608 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6609 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006610
Willy Tarreau95fa4692010-02-01 13:05:50 +01006611 uri_auth_compat_req[i++] = "unless";
6612 uri_auth_compat_req[i++] = "{";
6613 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6614 uri_auth_compat_req[i++] = "}";
6615 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006616
Willy Tarreauff011f22011-01-06 17:51:27 +01006617 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6618 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006619 cfgerr++;
6620 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006621 }
6622
Willy Tarreauff011f22011-01-06 17:51:27 +01006623 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006624
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006625 if (curproxy->uri_auth->auth_realm) {
6626 free(curproxy->uri_auth->auth_realm);
6627 curproxy->uri_auth->auth_realm = NULL;
6628 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006629
6630 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006631 }
6632out_uri_auth_compat:
6633
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006634 /* compile the log format */
6635 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006636 if (curproxy->conf.logformat_string != default_http_log_format &&
6637 curproxy->conf.logformat_string != default_tcp_log_format &&
6638 curproxy->conf.logformat_string != clf_http_log_format)
6639 free(curproxy->conf.logformat_string);
6640 curproxy->conf.logformat_string = NULL;
6641 free(curproxy->conf.lfs_file);
6642 curproxy->conf.lfs_file = NULL;
6643 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006644 }
6645
Willy Tarreau62a61232013-04-12 18:13:46 +02006646 if (curproxy->conf.logformat_string) {
6647 curproxy->conf.args.ctx = ARGC_LOG;
6648 curproxy->conf.args.file = curproxy->conf.lfs_file;
6649 curproxy->conf.args.line = curproxy->conf.lfs_line;
6650 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006651 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006652 curproxy->conf.args.file = NULL;
6653 curproxy->conf.args.line = 0;
6654 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006655
Willy Tarreau62a61232013-04-12 18:13:46 +02006656 if (curproxy->conf.uniqueid_format_string) {
6657 curproxy->conf.args.ctx = ARGC_UIF;
6658 curproxy->conf.args.file = curproxy->conf.uif_file;
6659 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006660 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006661 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006662 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006663 curproxy->conf.args.file = NULL;
6664 curproxy->conf.args.line = 0;
6665 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006666
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006667 /* only now we can check if some args remain unresolved.
6668 * This must be done after the users and groups resolution.
6669 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006670 cfgerr += smp_resolve_args(curproxy);
6671 if (!cfgerr)
6672 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006673
Willy Tarreau2738a142006-07-08 17:28:09 +02006674 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006675 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006676 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006677 (!curproxy->timeout.connect ||
6678 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006679 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006680 " | While not properly invalid, you will certainly encounter various problems\n"
6681 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006682 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006683 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006684 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006685 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006686
Willy Tarreau1fa31262007-12-03 00:36:16 +01006687 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6688 * We must still support older configurations, so let's find out whether those
6689 * parameters have been set or must be copied from contimeouts.
6690 */
6691 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006692 if (!curproxy->timeout.tarpit ||
6693 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006694 /* tarpit timeout not set. We search in the following order:
6695 * default.tarpit, curr.connect, default.connect.
6696 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006697 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006698 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006699 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006700 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006701 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006702 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006703 }
6704 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006705 (!curproxy->timeout.queue ||
6706 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006707 /* queue timeout not set. We search in the following order:
6708 * default.queue, curr.connect, default.connect.
6709 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006710 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006711 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006712 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006713 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006714 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006715 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006716 }
6717 }
6718
Willy Tarreau1620ec32011-08-06 17:05:02 +02006719 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006720 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6721 curproxy->check_req = (char *)malloc(curproxy->check_len);
6722 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006723 }
6724
Willy Tarreau215663d2014-06-13 18:30:23 +02006725 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6726 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6727 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6728 proxy_type_str(curproxy), curproxy->id);
6729 err_code |= ERR_WARN;
6730 }
6731
Willy Tarreau193b8c62012-11-22 00:17:38 +01006732 /* ensure that cookie capture length is not too large */
6733 if (curproxy->capture_len >= global.tune.cookie_len) {
6734 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6735 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6736 err_code |= ERR_WARN;
6737 curproxy->capture_len = global.tune.cookie_len - 1;
6738 }
6739
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006740 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006741 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006742 curproxy->req_cap_pool = create_pool("ptrcap",
6743 curproxy->nb_req_cap * sizeof(char *),
6744 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006745 }
6746
6747 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006748 curproxy->rsp_cap_pool = create_pool("ptrcap",
6749 curproxy->nb_rsp_cap * sizeof(char *),
6750 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006751 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006752
Willy Tarreaubaaee002006-06-26 02:48:02 +02006753 /* first, we will invert the servers list order */
6754 newsrv = NULL;
6755 while (curproxy->srv) {
6756 struct server *next;
6757
6758 next = curproxy->srv->next;
6759 curproxy->srv->next = newsrv;
6760 newsrv = curproxy->srv;
6761 if (!next)
6762 break;
6763 curproxy->srv = next;
6764 }
6765
Willy Tarreau17edc812014-01-03 12:14:34 +01006766 /* Check that no server name conflicts. This causes trouble in the stats.
6767 * We only emit a warning for the first conflict affecting each server,
6768 * in order to avoid combinatory explosion if all servers have the same
6769 * name. We do that only for servers which do not have an explicit ID,
6770 * because these IDs were made also for distinguishing them and we don't
6771 * want to annoy people who correctly manage them.
6772 */
6773 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6774 struct server *other_srv;
6775
6776 if (newsrv->puid)
6777 continue;
6778
6779 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6780 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6781 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6782 newsrv->conf.file, newsrv->conf.line,
6783 proxy_type_str(curproxy), curproxy->id,
6784 newsrv->id, other_srv->conf.line);
6785 break;
6786 }
6787 }
6788 }
6789
Willy Tarreaudd701652010-05-25 23:03:02 +02006790 /* assign automatic UIDs to servers which don't have one yet */
6791 next_id = 1;
6792 newsrv = curproxy->srv;
6793 while (newsrv != NULL) {
6794 if (!newsrv->puid) {
6795 /* server ID not set, use automatic numbering with first
6796 * spare entry starting with next_svid.
6797 */
6798 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6799 newsrv->conf.id.key = newsrv->puid = next_id;
6800 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6801 }
6802 next_id++;
6803 newsrv = newsrv->next;
6804 }
6805
Willy Tarreau20697042007-11-15 23:26:18 +01006806 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006807 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006808
Willy Tarreau62c3be22012-01-20 13:12:32 +01006809 /*
6810 * If this server supports a maxconn parameter, it needs a dedicated
6811 * tasks to fill the emptied slots when a connection leaves.
6812 * Also, resolve deferred tracking dependency if needed.
6813 */
6814 newsrv = curproxy->srv;
6815 while (newsrv != NULL) {
6816 if (newsrv->minconn > newsrv->maxconn) {
6817 /* Only 'minconn' was specified, or it was higher than or equal
6818 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6819 * this will avoid further useless expensive computations.
6820 */
6821 newsrv->maxconn = newsrv->minconn;
6822 } else if (newsrv->maxconn && !newsrv->minconn) {
6823 /* minconn was not specified, so we set it to maxconn */
6824 newsrv->minconn = newsrv->maxconn;
6825 }
6826
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006827#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006828 if (newsrv->use_ssl || newsrv->check.use_ssl)
6829 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006830#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006831
Willy Tarreau2f075e92013-12-03 11:11:34 +01006832 /* set the check type on the server */
6833 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6834
Willy Tarreau62c3be22012-01-20 13:12:32 +01006835 if (newsrv->trackit) {
6836 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006837 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006838 char *pname, *sname;
6839
6840 pname = newsrv->trackit;
6841 sname = strrchr(pname, '/');
6842
6843 if (sname)
6844 *sname++ = '\0';
6845 else {
6846 sname = pname;
6847 pname = NULL;
6848 }
6849
6850 if (pname) {
6851 px = findproxy(pname, PR_CAP_BE);
6852 if (!px) {
6853 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6854 proxy_type_str(curproxy), curproxy->id,
6855 newsrv->id, pname);
6856 cfgerr++;
6857 goto next_srv;
6858 }
6859 } else
6860 px = curproxy;
6861
6862 srv = findserver(px, sname);
6863 if (!srv) {
6864 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6865 proxy_type_str(curproxy), curproxy->id,
6866 newsrv->id, sname);
6867 cfgerr++;
6868 goto next_srv;
6869 }
6870
Willy Tarreau32091232014-05-16 13:52:00 +02006871 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6872 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6873 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006874 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006875 "tracking as it does not have any check nor agent enabled.\n",
6876 proxy_type_str(curproxy), curproxy->id,
6877 newsrv->id, px->id, srv->id);
6878 cfgerr++;
6879 goto next_srv;
6880 }
6881
6882 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6883
6884 if (loop) {
6885 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6886 "belongs to a tracking chain looping back to %s/%s.\n",
6887 proxy_type_str(curproxy), curproxy->id,
6888 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006889 cfgerr++;
6890 goto next_srv;
6891 }
6892
6893 if (curproxy != px &&
6894 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6895 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6896 "tracking: disable-on-404 option inconsistency.\n",
6897 proxy_type_str(curproxy), curproxy->id,
6898 newsrv->id, px->id, srv->id);
6899 cfgerr++;
6900 goto next_srv;
6901 }
6902
6903 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006904 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006905 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006906 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006907 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006908 }
6909
6910 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006911 newsrv->tracknext = srv->trackers;
6912 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006913
6914 free(newsrv->trackit);
6915 newsrv->trackit = NULL;
6916 }
6917 next_srv:
6918 newsrv = newsrv->next;
6919 }
6920
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006921 /* We have to initialize the server lookup mechanism depending
6922 * on what LB algorithm was choosen.
6923 */
6924
6925 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6926 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6927 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006928 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6929 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6930 init_server_map(curproxy);
6931 } else {
6932 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6933 fwrr_init_server_groups(curproxy);
6934 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006935 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006936
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006937 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006938 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6939 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6940 fwlc_init_server_tree(curproxy);
6941 } else {
6942 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6943 fas_init_server_tree(curproxy);
6944 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006945 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006946
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006947 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006948 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6949 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6950 chash_init_server_tree(curproxy);
6951 } else {
6952 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6953 init_server_map(curproxy);
6954 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006955 break;
6956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006957
6958 if (curproxy->options & PR_O_LOGASAP)
6959 curproxy->to_log &= ~LW_BYTES;
6960
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006961 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006962 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006963 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6964 proxy_type_str(curproxy), curproxy->id);
6965 err_code |= ERR_WARN;
6966 }
6967
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006968 if (curproxy->mode != PR_MODE_HTTP) {
6969 int optnum;
6970
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006971 if (curproxy->uri_auth) {
6972 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6973 proxy_type_str(curproxy), curproxy->id);
6974 err_code |= ERR_WARN;
6975 curproxy->uri_auth = NULL;
6976 }
6977
Willy Tarreau87cf5142011-08-19 22:57:24 +02006978 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006979 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6980 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6981 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006982 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006983 }
6984
6985 if (curproxy->options & PR_O_ORGTO) {
6986 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6987 "originalto", proxy_type_str(curproxy), curproxy->id);
6988 err_code |= ERR_WARN;
6989 curproxy->options &= ~PR_O_ORGTO;
6990 }
6991
6992 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6993 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6994 (curproxy->cap & cfg_opts[optnum].cap) &&
6995 (curproxy->options & cfg_opts[optnum].val)) {
6996 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6997 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6998 err_code |= ERR_WARN;
6999 curproxy->options &= ~cfg_opts[optnum].val;
7000 }
7001 }
7002
7003 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7004 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7005 (curproxy->cap & cfg_opts2[optnum].cap) &&
7006 (curproxy->options2 & cfg_opts2[optnum].val)) {
7007 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7008 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7009 err_code |= ERR_WARN;
7010 curproxy->options2 &= ~cfg_opts2[optnum].val;
7011 }
7012 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007013
Pieter Baauwd551fb52013-05-08 22:49:23 +02007014#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007015 if (curproxy->conn_src.bind_hdr_occ) {
7016 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007017 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007018 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007019 err_code |= ERR_WARN;
7020 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007021#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007022 }
7023
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007025 * ensure that we're not cross-dressing a TCP server into HTTP.
7026 */
7027 newsrv = curproxy->srv;
7028 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007029 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007030 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7031 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007032 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007033 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007034
Willy Tarreau0cec3312011-10-31 13:49:26 +01007035 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7036 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7037 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7038 err_code |= ERR_WARN;
7039 }
7040
Willy Tarreauc93cd162014-05-13 15:54:22 +02007041 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007042 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7043 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7044 err_code |= ERR_WARN;
7045 }
7046
Pieter Baauwd551fb52013-05-08 22:49:23 +02007047#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007048 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7049 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007050 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 +01007051 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007052 err_code |= ERR_WARN;
7053 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007054#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007055 newsrv = newsrv->next;
7056 }
7057
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007058 /* check if we have a frontend with "tcp-request content" looking at L7
7059 * with no inspect-delay
7060 */
7061 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7062 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7063 if (trule->action == TCP_ACT_CAPTURE &&
7064 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7065 break;
7066 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7067 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7068 break;
7069 }
7070
7071 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7072 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7073 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7074 " This means that these rules will randomly find their contents. This can be fixed by"
7075 " setting the tcp-request inspect-delay.\n",
7076 proxy_type_str(curproxy), curproxy->id);
7077 err_code |= ERR_WARN;
7078 }
7079 }
7080
Willy Tarreauc1a21672009-08-16 22:37:44 +02007081 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007082 if (!curproxy->accept)
7083 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007084
Willy Tarreauc1a21672009-08-16 22:37:44 +02007085 if (curproxy->tcp_req.inspect_delay ||
7086 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007087 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007088
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007089 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007090 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007091 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007092 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007093
7094 /* both TCP and HTTP must check switching rules */
7095 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7096 }
7097
7098 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007099 if (curproxy->tcp_req.inspect_delay ||
7100 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7101 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7102
Emeric Brun97679e72010-09-23 17:56:44 +02007103 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7104 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7105
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007106 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007107 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007108 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007109 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007110
7111 /* If the backend does requires RDP cookie persistence, we have to
7112 * enable the corresponding analyser.
7113 */
7114 if (curproxy->options2 & PR_O2_RDPC_PRST)
7115 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7116 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007117 }
7118
7119 /***********************************************************/
7120 /* At this point, target names have already been resolved. */
7121 /***********************************************************/
7122
7123 /* Check multi-process mode compatibility */
7124
7125 if (global.nbproc > 1 && global.stats_fe) {
7126 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7127 unsigned long mask;
7128
7129 mask = nbits(global.nbproc);
7130 if (global.stats_fe->bind_proc)
7131 mask &= global.stats_fe->bind_proc;
7132
7133 if (bind_conf->bind_proc)
7134 mask &= bind_conf->bind_proc;
7135
7136 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007137 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007138 break;
7139 }
7140 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7141 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");
7142 }
7143 }
7144
7145 /* Make each frontend inherit bind-process from its listeners when not specified. */
7146 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7147 if (curproxy->bind_proc)
7148 continue;
7149
7150 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7151 unsigned long mask;
7152
Willy Tarreau01760ad2015-05-04 21:57:58 +02007153 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007154 curproxy->bind_proc |= mask;
7155 }
7156
7157 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007158 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007159 }
7160
7161 if (global.stats_fe) {
7162 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7163 unsigned long mask;
7164
Cyril Bonté32e4f252016-02-24 00:14:54 +01007165 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau91b00c22014-09-16 13:41:21 +02007166 global.stats_fe->bind_proc |= mask;
7167 }
7168 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007169 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007170 }
7171
Willy Tarreaub3228c82014-10-01 20:50:17 +02007172 /* propagate bindings from frontends to backends. Don't do it if there
7173 * are any fatal errors as we must not call it with unresolved proxies.
7174 */
7175 if (!cfgerr) {
7176 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7177 if (curproxy->cap & PR_CAP_FE)
7178 propagate_processes(curproxy, NULL);
7179 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007180 }
7181
7182 /* Bind each unbound backend to all processes when not specified. */
7183 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7184 if (curproxy->bind_proc)
7185 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007186 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007187 }
7188
7189 /*******************************************************/
7190 /* At this step, all proxies have a non-null bind_proc */
7191 /*******************************************************/
7192
7193 /* perform the final checks before creating tasks */
7194
7195 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7196 struct listener *listener;
7197 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007198
Emeric Brunc52962f2012-11-15 18:28:02 +01007199#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007200 /* Configure SSL for each bind line.
7201 * Note: if configuration fails at some point, the ->ctx member
7202 * remains NULL so that listeners can later detach.
7203 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007204 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007205 int alloc_ctx;
7206
Emeric Brunc52962f2012-11-15 18:28:02 +01007207 if (!bind_conf->is_ssl) {
7208 if (bind_conf->default_ctx) {
7209 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7210 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7211 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007212 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007213 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007214 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007215 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007216 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007217 cfgerr++;
7218 continue;
7219 }
7220
Emeric Brun8dc60392014-05-09 13:52:00 +02007221 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007222 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007223 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7224 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
7225 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007226 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007227 cfgerr++;
7228 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007229 }
7230
Emeric Brunfc0421f2012-09-07 17:30:07 +02007231 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007232 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007233 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007234#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007235
Willy Tarreaue6b98942007-10-29 01:09:36 +01007236 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007237 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007238 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau434bc8d2016-04-14 11:47:38 +02007239 int nbproc;
7240
7241 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bontéc6d173f2016-04-15 07:58:43 +02007242 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau434bc8d2016-04-14 11:47:38 +02007243 nbits(global.nbproc));
7244
7245 if (!nbproc) /* no intersection between listener and frontend */
7246 nbproc = 1;
7247
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007248 if (!listener->luid) {
7249 /* listener ID not set, use automatic numbering with first
7250 * spare entry starting with next_luid.
7251 */
7252 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7253 listener->conf.id.key = listener->luid = next_id;
7254 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007255 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007256 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007257
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007258 /* enable separate counters */
7259 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7260 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007261 if (!listener->name)
7262 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007263 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007264
Willy Tarreaue6b98942007-10-29 01:09:36 +01007265 if (curproxy->options & PR_O_TCP_NOLING)
7266 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007267 if (!listener->maxconn)
7268 listener->maxconn = curproxy->maxconn;
7269 if (!listener->backlog)
7270 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007271 if (!listener->maxaccept)
7272 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7273
7274 /* we want to have an optimal behaviour on single process mode to
7275 * maximize the work at once, but in multi-process we want to keep
7276 * some fairness between processes, so we target half of the max
7277 * number of events to be balanced over all the processes the proxy
7278 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7279 * used to disable the limit.
7280 */
7281 if (listener->maxaccept > 0) {
7282 if (nbproc > 1)
7283 listener->maxaccept = (listener->maxaccept + 1) / 2;
7284 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7285 }
7286
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007287 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007288 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007289 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007290 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007291
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007292 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7293 listener->options |= LI_O_TCP_RULES;
7294
Willy Tarreaude3041d2010-05-31 10:56:17 +02007295 if (curproxy->mon_mask.s_addr)
7296 listener->options |= LI_O_CHK_MONNET;
7297
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007298 /* smart accept mode is automatic in HTTP mode */
7299 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007300 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007301 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7302 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007303 }
7304
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007305 /* Release unused SSL configs */
7306 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7307 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007308 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007309#ifdef USE_OPENSSL
7310 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007311 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007312 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007313 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007314 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007315#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007316 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007317
Willy Tarreau434bc8d2016-04-14 11:47:38 +02007318 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02007319 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007320 int count, maxproc = 0;
7321
7322 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007323 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007324 if (count > maxproc)
7325 maxproc = count;
7326 }
7327 /* backends have 0, frontends have 1 or more */
7328 if (maxproc != 1)
7329 Warning("Proxy '%s': in multi-process mode, stats will be"
7330 " limited to process assigned to the current request.\n",
7331 curproxy->id);
7332
Willy Tarreau102df612014-05-07 23:56:38 +02007333 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7334 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7335 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007336 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007337 }
Willy Tarreau102df612014-05-07 23:56:38 +02007338 if (curproxy->appsession_name) {
7339 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7340 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007341 }
Willy Tarreau102df612014-05-07 23:56:38 +02007342 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7343 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7344 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007345 }
7346 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007347
7348 /* create the task associated with the proxy */
7349 curproxy->task = task_new();
7350 if (curproxy->task) {
7351 curproxy->task->context = curproxy;
7352 curproxy->task->process = manage_proxy;
7353 /* no need to queue, it will be done automatically if some
7354 * listener gets limited.
7355 */
7356 curproxy->task->expire = TICK_ETERNITY;
7357 } else {
7358 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7359 curproxy->id);
7360 cfgerr++;
7361 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007362 }
7363
Willy Tarreaufbb78422011-06-05 15:38:35 +02007364 /* automatically compute fullconn if not set. We must not do it in the
7365 * loop above because cross-references are not yet fully resolved.
7366 */
7367 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7368 /* If <fullconn> is not set, let's set it to 10% of the sum of
7369 * the possible incoming frontend's maxconns.
7370 */
7371 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7372 struct proxy *fe;
7373 int total = 0;
7374
7375 /* sum up the number of maxconns of frontends which
7376 * reference this backend at least once or which are
7377 * the same one ('listen').
7378 */
7379 for (fe = proxy; fe; fe = fe->next) {
7380 struct switching_rule *rule;
7381 struct hdr_exp *exp;
7382 int found = 0;
7383
7384 if (!(fe->cap & PR_CAP_FE))
7385 continue;
7386
7387 if (fe == curproxy) /* we're on a "listen" instance */
7388 found = 1;
7389
7390 if (fe->defbe.be == curproxy) /* "default_backend" */
7391 found = 1;
7392
7393 /* check if a "use_backend" rule matches */
7394 if (!found) {
7395 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007396 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007397 found = 1;
7398 break;
7399 }
7400 }
7401 }
7402
7403 /* check if a "reqsetbe" rule matches */
7404 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7405 if (exp->action == ACT_SETBE &&
7406 (struct proxy *)exp->replace == curproxy) {
7407 found = 1;
7408 break;
7409 }
7410 }
7411
7412 /* now we've checked all possible ways to reference a backend
7413 * from a frontend.
7414 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007415 if (!found)
7416 continue;
7417 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007418 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007419 /* we have the sum of the maxconns in <total>. We only
7420 * keep 10% of that sum to set the default fullconn, with
7421 * a hard minimum of 1 (to avoid a divide by zero).
7422 */
7423 curproxy->fullconn = (total + 9) / 10;
7424 if (!curproxy->fullconn)
7425 curproxy->fullconn = 1;
7426 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007427 }
7428
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007429 /*
7430 * Recount currently required checks.
7431 */
7432
7433 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7434 int optnum;
7435
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007436 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7437 if (curproxy->options & cfg_opts[optnum].val)
7438 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007439
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007440 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7441 if (curproxy->options2 & cfg_opts2[optnum].val)
7442 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007443 }
7444
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007445 /* compute the required process bindings for the peers */
7446 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7447 if (curproxy->table.peers.p)
7448 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7449
Willy Tarreau122541c2011-09-07 21:24:49 +02007450 if (peers) {
7451 struct peers *curpeers = peers, **last;
7452 struct peer *p, *pb;
7453
Willy Tarreauab0419d2015-05-01 19:15:17 +02007454 /* Remove all peers sections which don't have a valid listener,
7455 * which are not used by any table, or which are bound to more
7456 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007457 */
7458 last = &peers;
7459 while (*last) {
7460 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007461
7462 if (curpeers->state == PR_STSTOPPED) {
7463 /* the "disabled" keyword was present */
7464 if (curpeers->peers_fe)
7465 stop_proxy(curpeers->peers_fe);
7466 curpeers->peers_fe = NULL;
7467 }
7468 else if (!curpeers->peers_fe) {
7469 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7470 curpeers->id, localpeer);
7471 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007472 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007473 /* either it's totally stopped or too much used */
7474 if (curpeers->peers_fe->bind_proc) {
7475 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007476 "running in different processes (%d different ones). "
7477 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007478 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007479 cfgerr++;
7480 }
7481 stop_proxy(curpeers->peers_fe);
7482 curpeers->peers_fe = NULL;
7483 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007484 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007485 last = &curpeers->next;
7486 continue;
7487 }
7488
Willy Tarreau34d05b02015-05-01 20:02:17 +02007489 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007490 p = curpeers->remote;
7491 while (p) {
7492 pb = p->next;
7493 free(p->id);
7494 free(p);
7495 p = pb;
7496 }
7497
7498 /* Destroy and unlink this curpeers section.
7499 * Note: curpeers is backed up into *last.
7500 */
7501 free(curpeers->id);
7502 curpeers = curpeers->next;
7503 free(*last);
7504 *last = curpeers;
7505 }
7506 }
7507
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007508 /* initialize stick-tables on backend capable proxies. This must not
7509 * be done earlier because the data size may be discovered while parsing
7510 * other proxies.
7511 */
7512 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7513 if (curproxy->state == PR_STSTOPPED)
7514 continue;
7515
7516 if (!stktable_init(&curproxy->table)) {
7517 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7518 cfgerr++;
7519 }
7520 }
7521
Willy Tarreau34eb6712011-10-24 18:15:04 +02007522 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007523 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007524 MEM_F_SHARED);
7525
Willy Tarreaubb925012009-07-23 13:36:36 +02007526 if (cfgerr > 0)
7527 err_code |= ERR_ALERT | ERR_FATAL;
7528 out:
7529 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007530}
7531
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007532/*
7533 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7534 * parsing sessions.
7535 */
7536void cfg_register_keywords(struct cfg_kw_list *kwl)
7537{
7538 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7539}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007540
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007541/*
7542 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7543 */
7544void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7545{
7546 LIST_DEL(&kwl->list);
7547 LIST_INIT(&kwl->list);
7548}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007549
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007550/* this function register new section in the haproxy configuration file.
7551 * <section_name> is the name of this new section and <section_parser>
7552 * is the called parser. If two section declaration have the same name,
7553 * only the first declared is used.
7554 */
7555int cfg_register_section(char *section_name,
7556 int (*section_parser)(const char *, int, char **, int))
7557{
7558 struct cfg_section *cs;
7559
7560 cs = calloc(1, sizeof(*cs));
7561 if (!cs) {
7562 Alert("register section '%s': out of memory.\n", section_name);
7563 return 0;
7564 }
7565
7566 cs->section_name = section_name;
7567 cs->section_parser = section_parser;
7568
7569 LIST_ADDQ(&sections, &cs->list);
7570
7571 return 1;
7572}
7573
Willy Tarreaubaaee002006-06-26 02:48:02 +02007574/*
7575 * Local variables:
7576 * c-indent-level: 8
7577 * c-basic-offset: 8
7578 * End:
7579 */