blob: e6e65b4fd0bc7d7cd6695b68b61e58b561b1b5ed [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
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int 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 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200315 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 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 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200597 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
598 global.tune.sslprivatecache = 1;
599 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100600 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.sslcachesize = atol(args[1]);
607 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100608 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
609 unsigned int ssllifetime;
610 const char *res;
611
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617
618 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
619 if (res) {
620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
621 file, linenum, *res, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625
626 global.tune.ssllifetime = ssllifetime;
627 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100628 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.ssl_max_record = atol(args[1]);
635 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200636 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.ssl_default_dh_param = atol(args[1]);
643 if (global.tune.ssl_default_dh_param < 1024) {
644 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200650 else if (!strcmp(args[0], "tune.bufsize")) {
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.bufsize = atol(args[1]);
657 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
658 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100659 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100660 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200661 }
662 else if (!strcmp(args[0], "tune.maxrewrite")) {
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668 global.tune.maxrewrite = atol(args[1]);
669 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
670 global.tune.maxrewrite = global.tune.bufsize / 2;
671 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100672 else if (!strcmp(args[0], "tune.idletimer")) {
673 unsigned int idle;
674 const char *res;
675
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681
682 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
683 if (res) {
684 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
685 file, linenum, *res, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689
690 if (idle > 65535) {
691 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.idle_timer = idle;
696 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100697 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
698 if (global.tune.client_rcvbuf != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT;
701 goto out;
702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.client_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
711 if (global.tune.server_rcvbuf != 0) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT;
714 goto out;
715 }
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.server_rcvbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.client")) {
724 if (global.tune.client_sndbuf != 0) {
725 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT;
727 goto out;
728 }
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.client_sndbuf = atol(args[1]);
735 }
736 else if (!strcmp(args[0], "tune.sndbuf.server")) {
737 if (global.tune.server_sndbuf != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT;
740 goto out;
741 }
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.server_sndbuf = atol(args[1]);
748 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200749 else if (!strcmp(args[0], "tune.pipesize")) {
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.pipesize = atol(args[1]);
756 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100757 else if (!strcmp(args[0], "tune.http.cookielen")) {
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.tune.cookie_len = atol(args[1]) + 1;
764 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200765 else if (!strcmp(args[0], "tune.http.maxhdr")) {
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.max_http_hdr = atol(args[1]);
772 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100773 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
774#ifdef USE_ZLIB
775 if (*args[1]) {
776 global.tune.zlibmemlevel = atoi(args[1]);
777 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
778 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
779 file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 } else {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789#else
790 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793#endif
794 }
795 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
796#ifdef USE_ZLIB
797 if (*args[1]) {
798 global.tune.zlibwindowsize = atoi(args[1]);
799 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
800 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
801 file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 } else {
806 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
807 file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811#else
812 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815#endif
816 }
William Lallemandf3747832012-11-09 12:33:10 +0100817 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
818 if (*args[1]) {
819 global.tune.comp_maxlevel = atoi(args[1]);
820 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
821 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
822 file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 } else {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "uid")) {
834 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 err_code |= ERR_ALERT;
837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 }
844 global.uid = atol(args[1]);
845 }
846 else if (!strcmp(args[0], "gid")) {
847 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200848 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT;
850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 }
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 }
857 global.gid = atol(args[1]);
858 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 /* user/group name handling */
860 else if (!strcmp(args[0], "user")) {
861 struct passwd *ha_user;
862 if (global.uid != 0) {
863 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT;
865 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200866 }
867 errno = 0;
868 ha_user = getpwnam(args[1]);
869 if (ha_user != NULL) {
870 global.uid = (int)ha_user->pw_uid;
871 }
872 else {
873 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 +0200874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200875 }
876 }
877 else if (!strcmp(args[0], "group")) {
878 struct group *ha_group;
879 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200880 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 err_code |= ERR_ALERT;
882 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 }
884 errno = 0;
885 ha_group = getgrnam(args[1]);
886 if (ha_group != NULL) {
887 global.gid = (int)ha_group->gr_gid;
888 }
889 else {
890 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 +0200891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200892 }
893 }
894 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100902 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
903 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
904 file, linenum, args[0], LONGBITS, global.nbproc);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 else if (!strcmp(args[0], "maxconn")) {
910 if (global.maxconn != 0) {
911 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
920 global.maxconn = atol(args[1]);
921#ifdef SYSTEM_MAXCONN
922 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
923 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);
924 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927#endif /* SYSTEM_MAXCONN */
928 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200929 else if (!strcmp(args[0], "maxsslconn")) {
930#ifdef USE_OPENSSL
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.maxsslconn = atol(args[1]);
937#else
Emeric Brun0914df82012-10-02 18:45:42 +0200938 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200941#endif
942 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100943 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
944#ifdef USE_OPENSSL
945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949 }
950 free(global.listen_default_ciphers);
951 global.listen_default_ciphers = strdup(args[1]);
952#else
953 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956#endif
957 }
958 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
959#ifdef USE_OPENSSL
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 free(global.connect_default_ciphers);
966 global.connect_default_ciphers = strdup(args[1]);
967#else
968 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
971#endif
972 }
Emeric Brun850efd52014-01-29 12:24:34 +0100973 else if (!strcmp(args[0], "ssl-server-verify")) {
974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979 if (strcmp(args[1],"none") == 0)
980 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
981 else if (strcmp(args[1],"required") == 0)
982 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
983 else {
984 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200989 else if (!strcmp(args[0], "maxconnrate")) {
990 if (global.cps_lim != 0) {
991 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
992 err_code |= ERR_ALERT;
993 goto out;
994 }
995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 global.cps_lim = atol(args[1]);
1001 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001002 else if (!strcmp(args[0], "maxsessrate")) {
1003 if (global.sps_lim != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT;
1006 goto out;
1007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 global.sps_lim = atol(args[1]);
1014 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001015 else if (!strcmp(args[0], "maxsslrate")) {
1016 if (global.ssl_lim != 0) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT;
1019 goto out;
1020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 global.ssl_lim = atol(args[1]);
1027 }
William Lallemandd85f9172012-11-09 17:05:39 +01001028 else if (!strcmp(args[0], "maxcomprate")) {
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034 global.comp_rate_lim = atoi(args[1]) * 1024;
1035 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001036 else if (!strcmp(args[0], "maxpipes")) {
1037 if (global.maxpipes != 0) {
1038 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT;
1040 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001041 }
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001046 }
1047 global.maxpipes = atol(args[1]);
1048 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001049 else if (!strcmp(args[0], "maxzlibmem")) {
1050 if (*(args[1]) == 0) {
1051 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
William Lallemande3a7d992012-11-20 11:25:20 +01001055 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001056 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001057 else if (!strcmp(args[0], "maxcompcpuusage")) {
1058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001064 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001065 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069}
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 else if (!strcmp(args[0], "ulimit-n")) {
1072 if (global.rlimit_nofile != 0) {
1073 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001074 err_code |= ERR_ALERT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 }
1082 global.rlimit_nofile = atol(args[1]);
1083 }
1084 else if (!strcmp(args[0], "chroot")) {
1085 if (global.chroot != NULL) {
1086 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 if (*(args[1]) == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
1095 global.chroot = strdup(args[1]);
1096 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 else if (!strcmp(args[0], "description")) {
1098 int i, len=0;
1099 char *d;
1100
1101 if (!*args[1]) {
1102 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1103 file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107
Willy Tarreau348acfe2014-04-14 15:00:39 +02001108 for (i = 1; *args[i]; i++)
1109 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001110
1111 if (global.desc)
1112 free(global.desc);
1113
1114 global.desc = d = (char *)calloc(1, len);
1115
Willy Tarreau348acfe2014-04-14 15:00:39 +02001116 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1117 for (i = 2; *args[i]; i++)
1118 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001119 }
1120 else if (!strcmp(args[0], "node")) {
1121 int i;
1122 char c;
1123
1124 for (i=0; args[1][i]; i++) {
1125 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001126 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1127 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001128 break;
1129 }
1130
1131 if (!i || args[1][i]) {
1132 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1133 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1134 file, linenum, args[0]);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
1137 }
1138
1139 if (global.node)
1140 free(global.node);
1141
1142 global.node = strdup(args[1]);
1143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 else if (!strcmp(args[0], "pidfile")) {
1145 if (global.pidfile != NULL) {
1146 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 if (*(args[1]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 global.pidfile = strdup(args[1]);
1156 }
Emeric Bruned760922010-10-22 17:59:25 +02001157 else if (!strcmp(args[0], "unix-bind")) {
1158 int cur_arg = 1;
1159 while (*(args[cur_arg])) {
1160 if (!strcmp(args[cur_arg], "prefix")) {
1161 if (global.unix_bind.prefix != NULL) {
1162 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1163 err_code |= ERR_ALERT;
1164 cur_arg += 2;
1165 continue;
1166 }
1167
1168 if (*(args[cur_arg+1]) == 0) {
1169 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172 }
1173 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1174 cur_arg += 2;
1175 continue;
1176 }
1177
1178 if (!strcmp(args[cur_arg], "mode")) {
1179
1180 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1181 cur_arg += 2;
1182 continue;
1183 }
1184
1185 if (!strcmp(args[cur_arg], "uid")) {
1186
1187 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1188 cur_arg += 2;
1189 continue;
1190 }
1191
1192 if (!strcmp(args[cur_arg], "gid")) {
1193
1194 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1195 cur_arg += 2;
1196 continue;
1197 }
1198
1199 if (!strcmp(args[cur_arg], "user")) {
1200 struct passwd *user;
1201
1202 user = getpwnam(args[cur_arg + 1]);
1203 if (!user) {
1204 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1205 file, linenum, args[0], args[cur_arg + 1 ]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208 }
1209
1210 global.unix_bind.ux.uid = user->pw_uid;
1211 cur_arg += 2;
1212 continue;
1213 }
1214
1215 if (!strcmp(args[cur_arg], "group")) {
1216 struct group *group;
1217
1218 group = getgrnam(args[cur_arg + 1]);
1219 if (!group) {
1220 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1221 file, linenum, args[0], args[cur_arg + 1 ]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 global.unix_bind.ux.gid = group->gr_gid;
1227 cur_arg += 2;
1228 continue;
1229 }
1230
Willy Tarreaub48f9582011-09-05 01:17:06 +02001231 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001232 file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 }
William Lallemand0f99e342011-10-12 17:50:54 +02001237 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1238 /* delete previous herited or defined syslog servers */
1239 struct logsrv *back;
1240 struct logsrv *tmp;
1241
1242 if (*(args[1]) != 0) {
1243 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1244 err_code |= ERR_ALERT | ERR_FATAL;
1245 goto out;
1246 }
1247
1248 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1249 LIST_DEL(&tmp->list);
1250 free(tmp);
1251 }
1252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001254 struct sockaddr_storage *sk;
1255 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001256 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001257 int arg = 0;
1258 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001259
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 if (*(args[1]) == 0 || *(args[2]) == 0) {
1261 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 }
William Lallemand0f99e342011-10-12 17:50:54 +02001265
1266 logsrv = calloc(1, sizeof(struct logsrv));
1267
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001268 /* just after the address, a length may be specified */
1269 if (strcmp(args[arg+2], "len") == 0) {
1270 len = atoi(args[arg+3]);
1271 if (len < 80 || len > 65535) {
1272 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1273 file, linenum, args[arg+3]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 logsrv->maxlen = len;
1278
1279 /* skip these two args */
1280 arg += 2;
1281 }
1282 else
1283 logsrv->maxlen = MAX_SYSLOG_LEN;
1284
1285 if (logsrv->maxlen > global.max_syslog_len) {
1286 global.max_syslog_len = logsrv->maxlen;
1287 logline = realloc(logline, global.max_syslog_len + 1);
1288 }
1289
1290 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001291 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001292 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001294 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001295 }
1296
William Lallemand0f99e342011-10-12 17:50:54 +02001297 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001298 if (*(args[arg+3])) {
1299 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001300 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001301 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001302 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001303 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 }
1305 }
1306
William Lallemand0f99e342011-10-12 17:50:54 +02001307 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001308 if (*(args[arg+4])) {
1309 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001310 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001311 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001313 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001314 }
1315 }
1316
Willy Tarreau902636f2013-03-10 19:44:48 +01001317 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001318 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001319 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001320 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001321 free(logsrv);
1322 goto out;
1323 }
1324 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001325
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001326 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001327 if (port1 != port2) {
1328 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1329 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001330 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001331 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001332 goto out;
1333 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001334
William Lallemand0f99e342011-10-12 17:50:54 +02001335 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001336 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001337 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339
William Lallemand0f99e342011-10-12 17:50:54 +02001340 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001341 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001342 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1343 char *name;
1344 int len;
1345
1346 if (global.log_send_hostname != NULL) {
1347 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1348 err_code |= ERR_ALERT;
1349 goto out;
1350 }
1351
1352 if (*(args[1]))
1353 name = args[1];
1354 else
1355 name = hostname;
1356
1357 len = strlen(name);
1358
1359 /* We'll add a space after the name to respect the log format */
1360 free(global.log_send_hostname);
1361 global.log_send_hostname = malloc(len + 2);
1362 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1363 }
Kevinm48936af2010-12-22 16:08:21 +00001364 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
1369 }
1370 free(global.log_tag);
1371 global.log_tag = strdup(args[1]);
1372 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001373 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1374 if (global.spread_checks != 0) {
1375 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001376 err_code |= ERR_ALERT;
1377 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001378 }
1379 if (*(args[1]) == 0) {
1380 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001383 }
1384 global.spread_checks = atol(args[1]);
1385 if (global.spread_checks < 0 || global.spread_checks > 50) {
1386 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001387 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001390 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1391 const char *err;
1392 unsigned int val;
1393
1394
1395 if (*(args[1]) == 0) {
1396 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto out;
1399 }
1400
1401 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1402 if (err) {
1403 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1404 err_code |= ERR_ALERT | ERR_FATAL;
1405 }
1406 global.max_spread_checks = val;
1407 if (global.max_spread_checks < 0) {
1408 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1409 err_code |= ERR_ALERT | ERR_FATAL;
1410 }
1411 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001412 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1413#ifdef USE_CPU_AFFINITY
1414 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001415 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001416 unsigned long cpus = 0;
1417
1418 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001419 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001420 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001421 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001422 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001423 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001424 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001425 proc = atol(args[1]);
1426 if (proc >= 1 && proc <= LONGBITS)
1427 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001428 }
1429
1430 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001431 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",
1432 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
1435 }
1436
1437 cur_arg = 2;
1438 while (*args[cur_arg]) {
1439 unsigned int low, high;
1440
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001441 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001442 char *dash = strchr(args[cur_arg], '-');
1443
1444 low = high = str2uic(args[cur_arg]);
1445 if (dash)
1446 high = str2uic(dash + 1);
1447
1448 if (high < low) {
1449 unsigned int swap = low;
1450 low = high;
1451 high = swap;
1452 }
1453
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001454 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001455 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001456 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
1459 }
1460
1461 while (low <= high)
1462 cpus |= 1UL << low++;
1463 }
1464 else {
1465 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1466 file, linenum, args[0], args[cur_arg]);
1467 err_code |= ERR_ALERT | ERR_FATAL;
1468 goto out;
1469 }
1470 cur_arg++;
1471 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001472 for (i = 0; i < LONGBITS; i++)
1473 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 global.cpu_map[i] = cpus;
1475#else
1476 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
1479#endif
1480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001482 struct cfg_kw_list *kwl;
1483 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001484 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001485
1486 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1487 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1488 if (kwl->kw[index].section != CFG_GLOBAL)
1489 continue;
1490 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001491 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001492 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001493 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001494 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001495 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001496 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001497 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001498 err_code |= ERR_WARN;
1499 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001500 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001501 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001502 }
1503 }
1504 }
1505
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001509
Willy Tarreau058e9072009-07-20 09:30:05 +02001510 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001511 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001512 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513}
1514
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001515void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001517 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 defproxy.mode = PR_MODE_TCP;
1519 defproxy.state = PR_STNEW;
1520 defproxy.maxconn = cfg_maxpconn;
1521 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001522
Simon Horman66183002013-02-23 10:16:43 +09001523 defproxy.defsrv.check.inter = DEF_CHKINTR;
1524 defproxy.defsrv.check.fastinter = 0;
1525 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001526 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1527 defproxy.defsrv.agent.fastinter = 0;
1528 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001529 defproxy.defsrv.check.rise = DEF_RISETIME;
1530 defproxy.defsrv.check.fall = DEF_FALLTIME;
1531 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1532 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001533 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001534 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001535 defproxy.defsrv.maxqueue = 0;
1536 defproxy.defsrv.minconn = 0;
1537 defproxy.defsrv.maxconn = 0;
1538 defproxy.defsrv.slowstart = 0;
1539 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1540 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1541 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542}
1543
Willy Tarreauade5ec42010-01-28 19:33:49 +01001544
Willy Tarreau63af98d2014-05-18 08:11:41 +02001545/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1546 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1547 * ERR_FATAL in case of error.
1548 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001549static int create_cond_regex_rule(const char *file, int line,
1550 struct proxy *px, int dir, int action, int flags,
1551 const char *cmd, const char *reg, const char *repl,
1552 const char **cond_start)
1553{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001554 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001555 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001556 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001557 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001558 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001559 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001560 int cs;
1561 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001562
1563 if (px == &defproxy) {
1564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001565 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001566 goto err;
1567 }
1568
1569 if (*reg == 0) {
1570 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001571 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001572 goto err;
1573 }
1574
1575 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001576 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001577
Willy Tarreau5321c422010-01-28 20:35:13 +01001578 if (cond_start &&
1579 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001580 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1581 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1582 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001583 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001584 goto err;
1585 }
1586 }
1587 else if (cond_start && **cond_start) {
1588 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1589 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001590 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001591 goto err;
1592 }
1593
Willy Tarreau63af98d2014-05-18 08:11:41 +02001594 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001595 (dir == SMP_OPT_DIR_REQ) ?
1596 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1597 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1598 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001599
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001600 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001601 if (!preg) {
1602 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001603 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001604 goto err;
1605 }
1606
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001607 cs = !(flags & REG_ICASE);
1608 cap = !(flags & REG_NOSUB);
1609 error = NULL;
1610 if (!regex_comp(reg, preg, cs, cap, &error)) {
1611 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1612 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001613 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614 goto err;
1615 }
1616
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001617 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001618 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001619 if (repl && err) {
1620 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1621 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001622 ret_code |= ERR_ALERT | ERR_FATAL;
1623 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001624 }
1625
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001626 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001627 ret_code |= ERR_WARN;
1628
1629 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001630
Willy Tarreau63af98d2014-05-18 08:11:41 +02001631 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001632 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001633 err:
1634 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001635 free(errmsg);
1636 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001637}
1638
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001640 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001641 * Returns the error code, 0 if OK, or any combination of :
1642 * - ERR_ABORT: must abort ASAP
1643 * - ERR_FATAL: we can continue parsing but not start the service
1644 * - ERR_WARN: a warning has been emitted
1645 * - ERR_ALERT: an alert has been emitted
1646 * Only the two first ones can stop processing, the two others are just
1647 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001649int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1650{
1651 static struct peers *curpeers = NULL;
1652 struct peer *newpeer = NULL;
1653 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001654 struct bind_conf *bind_conf;
1655 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001656 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001657 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001658
1659 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001660 if (!*args[1]) {
1661 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001662 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001663 goto out;
1664 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001665
1666 err = invalid_char(args[1]);
1667 if (err) {
1668 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1669 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001670 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001671 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 }
1673
1674 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1675 /*
1676 * If there are two proxies with the same name only following
1677 * combinations are allowed:
1678 */
1679 if (strcmp(curpeers->id, args[1]) == 0) {
1680 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1681 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1682 err_code |= ERR_WARN;
1683 }
1684 }
1685
1686 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
1690 }
1691
1692 curpeers->next = peers;
1693 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001694 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001695 curpeers->conf.line = linenum;
1696 curpeers->last_change = now.tv_sec;
1697 curpeers->id = strdup(args[1]);
1698 }
1699 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001700 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001701 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001702 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001703
1704 if (!*args[2]) {
1705 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1706 file, linenum, args[0]);
1707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
1709 }
1710
1711 err = invalid_char(args[1]);
1712 if (err) {
1713 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1714 file, linenum, *err, args[1]);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
1719 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1720 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1721 err_code |= ERR_ALERT | ERR_ABORT;
1722 goto out;
1723 }
1724
1725 /* the peers are linked backwards first */
1726 curpeers->count++;
1727 newpeer->next = curpeers->remote;
1728 curpeers->remote = newpeer;
1729 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001730 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001731 newpeer->conf.line = linenum;
1732
1733 newpeer->last_change = now.tv_sec;
1734 newpeer->id = strdup(args[1]);
1735
Willy Tarreau902636f2013-03-10 19:44:48 +01001736 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001737 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001738 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001741 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001742
1743 proto = protocol_by_family(sk->ss_family);
1744 if (!proto || !proto->connect) {
1745 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1746 file, linenum, args[0], args[1]);
1747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
1749 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001750
1751 if (port1 != port2) {
1752 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1753 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
1756 }
1757
Willy Tarreau2aa38802013-02-20 19:20:59 +01001758 if (!port1) {
1759 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1760 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
1763 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001764
Emeric Brun32da3c42010-09-23 18:39:19 +02001765 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001766 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001767 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001768 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001769
Emeric Brun32da3c42010-09-23 18:39:19 +02001770 if (strcmp(newpeer->id, localpeer) == 0) {
1771 /* Current is local peer, it define a frontend */
1772 newpeer->local = 1;
1773
1774 if (!curpeers->peers_fe) {
1775 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1776 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1777 err_code |= ERR_ALERT | ERR_ABORT;
1778 goto out;
1779 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001780
Willy Tarreau237250c2011-07-29 01:49:03 +02001781 init_new_proxy(curpeers->peers_fe);
1782 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001783
1784 curpeers->peers_fe->last_change = now.tv_sec;
1785 curpeers->peers_fe->id = strdup(args[1]);
1786 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001787 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001788 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1789 curpeers->peers_fe->timeout.connect = 5000;
1790 curpeers->peers_fe->accept = peer_accept;
1791 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001792 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1793 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001794
1795 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1796
Willy Tarreau902636f2013-03-10 19:44:48 +01001797 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1798 if (errmsg && *errmsg) {
1799 indent_msg(&errmsg, 2);
1800 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001801 }
1802 else
1803 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1804 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001805 err_code |= ERR_FATAL;
1806 goto out;
1807 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001808
1809 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001810 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001811 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1812 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1813 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1814 l->accept = session_accept;
1815 l->handler = process_session;
1816 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1817 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1818 global.maxsock += l->maxconn;
1819 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001821 else {
1822 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1823 file, linenum, args[0], args[1],
1824 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1825 err_code |= ERR_FATAL;
1826 goto out;
1827 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001828 }
1829 } /* neither "peer" nor "peers" */
1830 else if (*args[0] != 0) {
1831 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
1836out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001838 return err_code;
1839}
1840
Willy Tarreau3842f002009-06-14 11:39:52 +02001841int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842{
1843 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001844 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001845 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001846 int rc;
1847 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001848 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001849 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001850 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001851 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001852 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 if (!strcmp(args[0], "listen"))
1855 rc = PR_CAP_LISTEN;
1856 else if (!strcmp(args[0], "frontend"))
1857 rc = PR_CAP_FE | PR_CAP_RS;
1858 else if (!strcmp(args[0], "backend"))
1859 rc = PR_CAP_BE | PR_CAP_RS;
1860 else if (!strcmp(args[0], "ruleset"))
1861 rc = PR_CAP_RS;
1862 else
1863 rc = PR_CAP_NONE;
1864
1865 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001866 struct ebpt_node *node;
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 if (!*args[1]) {
1869 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1870 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_ALERT | ERR_ABORT;
1873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001875
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001876 err = invalid_char(args[1]);
1877 if (err) {
1878 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1879 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001881 }
1882
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001883 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1884 curproxy = container_of(node, struct proxy, conf.by_name);
1885
1886 if (strcmp(curproxy->id, args[1]) != 0)
1887 break;
1888
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001889 /*
1890 * If there are two proxies with the same name only following
1891 * combinations are allowed:
1892 *
1893 * listen backend frontend ruleset
1894 * listen - - - -
1895 * backend - - OK -
1896 * frontend - OK - -
1897 * ruleset - - - -
1898 */
1899
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001900 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1901 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001902 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1903 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1904 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001906 }
1907 }
1908
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1910 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_ALERT | ERR_ABORT;
1912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001914
Willy Tarreau97cb7802010-01-03 20:23:58 +01001915 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 curproxy->next = proxy;
1917 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001918 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1919 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001920 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001923 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924
1925 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001927 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001928
Willy Tarreau4348fad2012-09-20 16:48:07 +02001929 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1930
Willy Tarreau902636f2013-03-10 19:44:48 +01001931 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1932 if (errmsg && *errmsg) {
1933 indent_msg(&errmsg, 2);
1934 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001935 }
1936 else
1937 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1938 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_FATAL;
1940 goto out;
1941 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001942
Willy Tarreau4348fad2012-09-20 16:48:07 +02001943 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001944 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
1947
1948 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001949 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001950 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001951
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001954 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001955 curproxy->no_options = defproxy.no_options;
1956 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001957 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001958 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001959 curproxy->except_net = defproxy.except_net;
1960 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001961 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001962 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001964 if (defproxy.fwdfor_hdr_len) {
1965 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1966 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1967 }
1968
Willy Tarreaub86db342009-11-30 11:50:16 +01001969 if (defproxy.orgto_hdr_len) {
1970 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1971 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1972 }
1973
Mark Lamourinec2247f02012-01-04 13:02:01 -05001974 if (defproxy.server_id_hdr_len) {
1975 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1976 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1977 }
1978
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 if (curproxy->cap & PR_CAP_FE) {
1980 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001981 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001982 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983
1984 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001985 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1986 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001987
1988 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991 if (curproxy->cap & PR_CAP_BE) {
1992 curproxy->fullconn = defproxy.fullconn;
1993 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001994 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001996 if (defproxy.check_req) {
1997 curproxy->check_req = calloc(1, defproxy.check_len);
1998 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1999 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002002 if (defproxy.expect_str) {
2003 curproxy->expect_str = strdup(defproxy.expect_str);
2004 if (defproxy.expect_regex) {
2005 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002006 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2007 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002008 }
2009 }
2010
Willy Tarreau67402132012-05-31 20:40:20 +02002011 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012 if (defproxy.cookie_name)
2013 curproxy->cookie_name = strdup(defproxy.cookie_name);
2014 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002015 if (defproxy.cookie_domain)
2016 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002017
Willy Tarreau31936852010-10-06 16:59:56 +02002018 if (defproxy.cookie_maxidle)
2019 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2020
2021 if (defproxy.cookie_maxlife)
2022 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2023
Emeric Brun647caf12009-06-30 17:57:00 +02002024 if (defproxy.rdp_cookie_name)
2025 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2026 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2027
Willy Tarreau01732802007-11-01 22:48:15 +01002028 if (defproxy.url_param_name)
2029 curproxy->url_param_name = strdup(defproxy.url_param_name);
2030 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002031
Benoitaffb4812009-03-25 13:02:10 +01002032 if (defproxy.hh_name)
2033 curproxy->hh_name = strdup(defproxy.hh_name);
2034 curproxy->hh_len = defproxy.hh_len;
2035 curproxy->hh_match_domain = defproxy.hh_match_domain;
2036
Willy Tarreauef9a3602012-12-08 22:29:20 +01002037 if (defproxy.conn_src.iface_name)
2038 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2039 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002040 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002041#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002042 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002043#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002046 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 if (defproxy.capture_name)
2048 curproxy->capture_name = strdup(defproxy.capture_name);
2049 curproxy->capture_namelen = defproxy.capture_namelen;
2050 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002054 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002055 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002056 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002057 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002058 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059 curproxy->mon_net = defproxy.mon_net;
2060 curproxy->mon_mask = defproxy.mon_mask;
2061 if (defproxy.monitor_uri)
2062 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2063 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002064 if (defproxy.defbe.name)
2065 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002066
2067 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002068 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2069 if (curproxy->conf.logformat_string &&
2070 curproxy->conf.logformat_string != default_http_log_format &&
2071 curproxy->conf.logformat_string != default_tcp_log_format &&
2072 curproxy->conf.logformat_string != clf_http_log_format)
2073 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2074
2075 if (defproxy.conf.lfs_file) {
2076 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2077 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 }
2080
2081 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002082 curproxy->timeout.connect = defproxy.timeout.connect;
2083 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002084 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002085 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002086 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002087 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002088 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002089 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002090 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002091 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002092 }
2093
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002095 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002096
2097 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002098 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002099 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002100 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002101 LIST_INIT(&node->list);
2102 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2103 }
2104
Willy Tarreau62a61232013-04-12 18:13:46 +02002105 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2106 if (curproxy->conf.uniqueid_format_string)
2107 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2108
2109 if (defproxy.conf.uif_file) {
2110 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2111 curproxy->conf.uif_line = defproxy.conf.uif_line;
2112 }
William Lallemanda73203e2012-03-12 12:48:57 +01002113
2114 /* copy default header unique id */
2115 if (defproxy.header_unique_id)
2116 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2117
William Lallemand82fe75c2012-10-23 10:25:10 +02002118 /* default compression options */
2119 if (defproxy.comp != NULL) {
2120 curproxy->comp = calloc(1, sizeof(struct comp));
2121 curproxy->comp->algos = defproxy.comp->algos;
2122 curproxy->comp->types = defproxy.comp->types;
2123 }
2124
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002126 curproxy->conf.used_listener_id = EB_ROOT;
2127 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002128
Willy Tarreau93893792009-07-23 13:19:11 +02002129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130 }
2131 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2132 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002133 /* FIXME-20070101: we should do this too at the end of the
2134 * config parsing to free all default values.
2135 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002136 free(defproxy.check_req);
2137 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002138 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002139 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002140 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002141 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002142 free(defproxy.capture_name);
2143 free(defproxy.monitor_uri);
2144 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002145 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002146 free(defproxy.fwdfor_hdr_name);
2147 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002148 free(defproxy.orgto_hdr_name);
2149 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002150 free(defproxy.server_id_hdr_name);
2151 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002152 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002153 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002154 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002155 free(defproxy.expect_regex);
2156 defproxy.expect_regex = NULL;
2157 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002158
Willy Tarreau62a61232013-04-12 18:13:46 +02002159 if (defproxy.conf.logformat_string != default_http_log_format &&
2160 defproxy.conf.logformat_string != default_tcp_log_format &&
2161 defproxy.conf.logformat_string != clf_http_log_format)
2162 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002163
Willy Tarreau62a61232013-04-12 18:13:46 +02002164 free(defproxy.conf.uniqueid_format_string);
2165 free(defproxy.conf.lfs_file);
2166 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002167
Willy Tarreaua534fea2008-08-03 12:19:50 +02002168 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002169 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002170
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 /* we cannot free uri_auth because it might already be used */
2172 init_default_instance();
2173 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002174 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2175 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 }
2179 else if (curproxy == NULL) {
2180 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002184
2185 /* update the current file and line being parsed */
2186 curproxy->conf.args.file = curproxy->conf.file;
2187 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002188
2189 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002190 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2191 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2192 if (err_code & ERR_FATAL)
2193 goto out;
2194 }
2195 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002196 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002197 int cur_arg;
2198
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 if (curproxy == &defproxy) {
2200 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002204 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206
Willy Tarreau24709282013-03-10 21:32:12 +01002207 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002208 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002213
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002214 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002215
2216 /* use default settings for unix sockets */
2217 bind_conf->ux.uid = global.unix_bind.ux.uid;
2218 bind_conf->ux.gid = global.unix_bind.ux.gid;
2219 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002220
2221 /* NOTE: the following line might create several listeners if there
2222 * are comma-separated IPs or port ranges. So all further processing
2223 * will have to be applied to all listeners created after last_listen.
2224 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002225 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2226 if (errmsg && *errmsg) {
2227 indent_msg(&errmsg, 2);
2228 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002229 }
2230 else
2231 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2232 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002236
Willy Tarreau4348fad2012-09-20 16:48:07 +02002237 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2238 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002239 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002240 }
2241
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002242 cur_arg = 2;
2243 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002244 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002245 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002246 char *err;
2247
Willy Tarreau26982662012-09-12 23:17:10 +02002248 kw = bind_find_kw(args[cur_arg]);
2249 if (kw) {
2250 char *err = NULL;
2251 int code;
2252
2253 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002254 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2255 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002256 cur_arg += 1 + kw->skip ;
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
2260
Willy Tarreau4348fad2012-09-20 16:48:07 +02002261 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002262 err_code |= code;
2263
2264 if (code) {
2265 if (err && *err) {
2266 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002267 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002268 }
2269 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002270 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2271 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002272 if (code & ERR_FATAL) {
2273 free(err);
2274 cur_arg += 1 + kw->skip;
2275 goto out;
2276 }
2277 }
2278 free(err);
2279 cur_arg += 1 + kw->skip;
2280 continue;
2281 }
2282
Willy Tarreau8638f482012-09-18 18:01:17 +02002283 err = NULL;
2284 if (!bind_dumped) {
2285 bind_dump_kws(&err);
2286 indent_msg(&err, 4);
2287 bind_dumped = 1;
2288 }
2289
2290 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2291 file, linenum, args[0], args[1], args[cur_arg],
2292 err ? " Registered keywords :" : "", err ? err : "");
2293 free(err);
2294
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002297 }
Willy Tarreau93893792009-07-23 13:19:11 +02002298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
2300 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002301 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2303 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002307 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 /* flush useless bits */
2311 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002314 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002315 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002316 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317
Willy Tarreau1c47f852006-07-09 08:22:27 +02002318 if (!*args[1]) {
2319 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002323 }
2324
Willy Tarreaua534fea2008-08-03 12:19:50 +02002325 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002326 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002327 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002328 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002329 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2330
Willy Tarreau93893792009-07-23 13:19:11 +02002331 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2334 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2335 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2336 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2337 else {
2338 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 }
2342 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002343 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002344 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002345
2346 if (curproxy == &defproxy) {
2347 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002351 }
2352
2353 if (!*args[1]) {
2354 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2355 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002358 }
2359
2360 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002361 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002362
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002363 if (curproxy->uuid <= 0) {
2364 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002365 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002368 }
2369
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002370 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2371 if (node) {
2372 struct proxy *target = container_of(node, struct proxy, conf.id);
2373 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2374 file, linenum, proxy_type_str(curproxy), curproxy->id,
2375 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
2378 }
2379 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002380 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002381 else if (!strcmp(args[0], "description")) {
2382 int i, len=0;
2383 char *d;
2384
Cyril Bonté99ed3272010-01-24 23:29:44 +01002385 if (curproxy == &defproxy) {
2386 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2387 file, linenum, args[0]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002392 if (!*args[1]) {
2393 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2394 file, linenum, args[0]);
2395 return -1;
2396 }
2397
Willy Tarreau348acfe2014-04-14 15:00:39 +02002398 for (i = 1; *args[i]; i++)
2399 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002400
2401 d = (char *)calloc(1, len);
2402 curproxy->desc = d;
2403
Willy Tarreau348acfe2014-04-14 15:00:39 +02002404 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2405 for (i = 2; *args[i]; i++)
2406 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002407
2408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2410 curproxy->state = PR_STSTOPPED;
2411 }
2412 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2413 curproxy->state = PR_STNEW;
2414 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002415 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2416 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002417 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002418
2419 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002420 unsigned int low, high;
2421
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002422 if (strcmp(args[cur_arg], "all") == 0) {
2423 set = 0;
2424 break;
2425 }
2426 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002427 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002428 }
2429 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002430 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002431 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002432 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002433 char *dash = strchr(args[cur_arg], '-');
2434
2435 low = high = str2uic(args[cur_arg]);
2436 if (dash)
2437 high = str2uic(dash + 1);
2438
2439 if (high < low) {
2440 unsigned int swap = low;
2441 low = high;
2442 high = swap;
2443 }
2444
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002445 if (low < 1 || high > LONGBITS) {
2446 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2447 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002450 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002451 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002452 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002453 }
2454 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002455 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2456 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002459 }
2460 cur_arg++;
2461 }
2462 curproxy->bind_proc = set;
2463 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002464 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002465 if (curproxy == &defproxy) {
2466 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002469 }
2470
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002471 err = invalid_char(args[1]);
2472 if (err) {
2473 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2474 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002476 }
2477
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002478 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002479 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2480 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002483 }
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2486 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002489 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 if (*(args[1]) == 0) {
2492 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002497
Willy Tarreau67402132012-05-31 20:40:20 +02002498 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002499 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002500 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002501 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 curproxy->cookie_name = strdup(args[1]);
2503 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002504
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 cur_arg = 2;
2506 while (*(args[cur_arg])) {
2507 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002508 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 }
2510 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002511 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002514 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 }
2516 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002517 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 }
2519 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002520 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002522 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002523 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002526 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002528 else if (!strcmp(args[cur_arg], "httponly")) {
2529 curproxy->ck_opts |= PR_CK_HTTPONLY;
2530 }
2531 else if (!strcmp(args[cur_arg], "secure")) {
2532 curproxy->ck_opts |= PR_CK_SECURE;
2533 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002534 else if (!strcmp(args[cur_arg], "domain")) {
2535 if (!*args[cur_arg + 1]) {
2536 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2537 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002540 }
2541
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002542 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002543 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002544 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2545 " dots nor does not start with a dot."
2546 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002547 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002548 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002549 }
2550
2551 err = invalid_domainchar(args[cur_arg + 1]);
2552 if (err) {
2553 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2554 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002557 }
2558
Willy Tarreau68a897b2009-12-03 23:28:34 +01002559 if (!curproxy->cookie_domain) {
2560 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2561 } else {
2562 /* one domain was already specified, add another one by
2563 * building the string which will be returned along with
2564 * the cookie.
2565 */
2566 char *new_ptr;
2567 int new_len = strlen(curproxy->cookie_domain) +
2568 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2569 new_ptr = malloc(new_len);
2570 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2571 free(curproxy->cookie_domain);
2572 curproxy->cookie_domain = new_ptr;
2573 }
Willy Tarreau31936852010-10-06 16:59:56 +02002574 cur_arg++;
2575 }
2576 else if (!strcmp(args[cur_arg], "maxidle")) {
2577 unsigned int maxidle;
2578 const char *res;
2579
2580 if (!*args[cur_arg + 1]) {
2581 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2582 file, linenum, args[cur_arg]);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586
2587 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2588 if (res) {
2589 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2590 file, linenum, *res, args[cur_arg]);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
2594 curproxy->cookie_maxidle = maxidle;
2595 cur_arg++;
2596 }
2597 else if (!strcmp(args[cur_arg], "maxlife")) {
2598 unsigned int maxlife;
2599 const char *res;
2600
2601 if (!*args[cur_arg + 1]) {
2602 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2603 file, linenum, args[cur_arg]);
2604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
2606 }
2607
2608 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2609 if (res) {
2610 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2611 file, linenum, *res, args[cur_arg]);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 cur_arg++;
2617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002619 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 +02002620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
2624 cur_arg++;
2625 }
Willy Tarreau67402132012-05-31 20:40:20 +02002626 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2628 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 }
2631
Willy Tarreau67402132012-05-31 20:40:20 +02002632 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2634 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002637
Willy Tarreau67402132012-05-31 20:40:20 +02002638 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002639 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2640 file, linenum);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002644 else if (!strcmp(args[0], "persist")) { /* persist */
2645 if (*(args[1]) == 0) {
2646 Alert("parsing [%s:%d] : missing persist method.\n",
2647 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002650 }
2651
2652 if (!strncmp(args[1], "rdp-cookie", 10)) {
2653 curproxy->options2 |= PR_O2_RDPC_PRST;
2654
Emeric Brunb982a3d2010-01-04 15:45:53 +01002655 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002656 const char *beg, *end;
2657
2658 beg = args[1] + 11;
2659 end = strchr(beg, ')');
2660
2661 if (!end || end == beg) {
2662 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2663 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002666 }
2667
2668 free(curproxy->rdp_cookie_name);
2669 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2670 curproxy->rdp_cookie_len = end-beg;
2671 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002672 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002673 free(curproxy->rdp_cookie_name);
2674 curproxy->rdp_cookie_name = strdup("msts");
2675 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2676 }
2677 else { /* syntax */
2678 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2679 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002682 }
2683 }
2684 else {
2685 Alert("parsing [%s:%d] : unknown persist method.\n",
2686 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002689 }
2690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002692 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002704 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 }
2709 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002710 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 curproxy->appsession_name = strdup(args[1]);
2712 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2713 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002714 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2715 if (err) {
2716 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2717 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002720 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002721 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002722
Willy Tarreau51041c72007-09-09 21:56:53 +02002723 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2724 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_ABORT;
2726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002728
2729 cur_arg = 6;
2730 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002731 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2732 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002733 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002734 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002735 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002736 } else if (!strcmp(args[cur_arg], "prefix")) {
2737 curproxy->options2 |= PR_O2_AS_PFX;
2738 } else if (!strcmp(args[cur_arg], "mode")) {
2739 if (!*args[cur_arg + 1]) {
2740 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2741 file, linenum, args[0], args[cur_arg]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745
2746 cur_arg++;
2747 if (!strcmp(args[cur_arg], "query-string")) {
2748 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2749 curproxy->options2 |= PR_O2_AS_M_QS;
2750 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2751 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2752 curproxy->options2 |= PR_O2_AS_M_PP;
2753 } else {
2754 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
2758 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002759 cur_arg++;
2760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 } /* Url App Session */
2762 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002763 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002765
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 if (*(args[4]) == 0) {
2774 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2775 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002779 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 curproxy->capture_name = strdup(args[2]);
2781 curproxy->capture_namelen = strlen(curproxy->capture_name);
2782 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 curproxy->to_log |= LW_COOKIE;
2784 }
2785 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2786 struct cap_hdr *hdr;
2787
2788 if (curproxy == &defproxy) {
2789 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 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 }
2793
2794 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2795 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2796 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 }
2800
2801 hdr = calloc(sizeof(struct cap_hdr), 1);
2802 hdr->next = curproxy->req_cap;
2803 hdr->name = strdup(args[3]);
2804 hdr->namelen = strlen(args[3]);
2805 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002806 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 hdr->index = curproxy->nb_req_cap++;
2808 curproxy->req_cap = hdr;
2809 curproxy->to_log |= LW_REQHDR;
2810 }
2811 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2812 struct cap_hdr *hdr;
2813
2814 if (curproxy == &defproxy) {
2815 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 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 }
2819
2820 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2821 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2822 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 }
2826 hdr = calloc(sizeof(struct cap_hdr), 1);
2827 hdr->next = curproxy->rsp_cap;
2828 hdr->name = strdup(args[3]);
2829 hdr->namelen = strlen(args[3]);
2830 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002831 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 hdr->index = curproxy->nb_rsp_cap++;
2833 curproxy->rsp_cap = hdr;
2834 curproxy->to_log |= LW_RSPHDR;
2835 }
2836 else {
2837 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2838 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002846
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 if (*(args[1]) == 0) {
2848 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 }
2853 curproxy->conn_retries = atol(args[1]);
2854 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002855 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002856 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002857
2858 if (curproxy == &defproxy) {
2859 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863
Willy Tarreau20b0de52012-12-24 15:45:22 +01002864 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2865 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2866 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2867 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002868 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002869 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2870 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 +01002871 file, linenum, args[0]);
2872 err_code |= ERR_WARN;
2873 }
2874
Willy Tarreauff011f22011-01-06 17:51:27 +01002875 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002876
Willy Tarreauff011f22011-01-06 17:51:27 +01002877 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002878 err_code |= ERR_ALERT | ERR_ABORT;
2879 goto out;
2880 }
2881
Willy Tarreau5002f572014-04-23 01:32:02 +02002882 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002883 err_code |= warnif_cond_conflicts(rule->cond,
2884 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2885 file, linenum);
2886
Willy Tarreauff011f22011-01-06 17:51:27 +01002887 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002888 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002889 else if (!strcmp(args[0], "http-response")) { /* response access control */
2890 struct http_res_rule *rule;
2891
2892 if (curproxy == &defproxy) {
2893 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
2898 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2899 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2900 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2901 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2902 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2903 file, linenum, args[0]);
2904 err_code |= ERR_WARN;
2905 }
2906
2907 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2908
2909 if (!rule) {
2910 err_code |= ERR_ALERT | ERR_ABORT;
2911 goto out;
2912 }
2913
2914 err_code |= warnif_cond_conflicts(rule->cond,
2915 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2916 file, linenum);
2917
2918 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2919 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002920 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2921 /* set the header name and length into the proxy structure */
2922 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2923 err_code |= ERR_WARN;
2924
2925 if (!*args[1]) {
2926 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2927 file, linenum, args[0]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931
2932 /* set the desired header name */
2933 free(curproxy->server_id_hdr_name);
2934 curproxy->server_id_hdr_name = strdup(args[1]);
2935 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2936 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002937 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002938 struct http_req_rule *rule;
2939
Willy Tarreaub099aca2008-10-12 17:26:37 +02002940 if (curproxy == &defproxy) {
2941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002944 }
2945
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002946 /* emulate "block" using "http-request block". Since these rules are supposed to
2947 * be processed before all http-request rules, we put them into their own list
2948 * and will insert them at the end.
2949 */
2950 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2951 if (!rule) {
2952 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002953 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002954 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002955 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2956 err_code |= warnif_cond_conflicts(rule->cond,
2957 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2958 file, linenum);
2959 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002960
2961 if (!already_warned(WARN_BLOCK_DEPRECATED))
2962 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]);
2963
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002964 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002965 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002966 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002967
Cyril Bonté99ed3272010-01-24 23:29:44 +01002968 if (curproxy == &defproxy) {
2969 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002974 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002975 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2976 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002979 }
2980
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002981 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002982 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002983 err_code |= warnif_cond_conflicts(rule->cond,
2984 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2985 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002986 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002987 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002988 struct switching_rule *rule;
2989
Willy Tarreaub099aca2008-10-12 17:26:37 +02002990 if (curproxy == &defproxy) {
2991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002994 }
2995
Willy Tarreau55ea7572007-06-17 19:56:27 +02002996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002998
2999 if (*(args[1]) == 0) {
3000 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003003 }
3004
Willy Tarreauf51658d2014-04-23 01:21:56 +02003005 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3006 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3007 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3008 file, linenum, errmsg);
3009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003012
Willy Tarreauf51658d2014-04-23 01:21:56 +02003013 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003014 }
3015
3016 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3017 rule->cond = cond;
3018 rule->be.name = strdup(args[1]);
3019 LIST_INIT(&rule->list);
3020 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3021 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003022 else if (strcmp(args[0], "use-server") == 0) {
3023 struct server_rule *rule;
3024
3025 if (curproxy == &defproxy) {
3026 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
3031 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3032 err_code |= ERR_WARN;
3033
3034 if (*(args[1]) == 0) {
3035 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
3039
3040 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3041 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3042 file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003047 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3048 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3049 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003054 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003055
3056 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3057 rule->cond = cond;
3058 rule->srv.name = strdup(args[1]);
3059 LIST_INIT(&rule->list);
3060 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3061 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3062 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003063 else if ((!strcmp(args[0], "force-persist")) ||
3064 (!strcmp(args[0], "ignore-persist"))) {
3065 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003066
3067 if (curproxy == &defproxy) {
3068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072
3073 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3074 err_code |= ERR_WARN;
3075
Willy Tarreauef6494c2010-01-28 17:12:36 +01003076 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003077 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3078 file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003083 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3084 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3085 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003090 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3091 * where force-persist is applied.
3092 */
3093 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003094
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003095 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003096 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003097 if (!strcmp(args[0], "force-persist")) {
3098 rule->type = PERSIST_TYPE_FORCE;
3099 } else {
3100 rule->type = PERSIST_TYPE_IGNORE;
3101 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003102 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003103 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003104 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003105 else if (!strcmp(args[0], "stick-table")) {
3106 int myidx = 1;
3107
Emeric Brun32da3c42010-09-23 18:39:19 +02003108 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003109 curproxy->table.type = (unsigned int)-1;
3110 while (*args[myidx]) {
3111 const char *err;
3112
3113 if (strcmp(args[myidx], "size") == 0) {
3114 myidx++;
3115 if (!*(args[myidx])) {
3116 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3117 file, linenum, args[myidx-1]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3122 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3123 file, linenum, *err, args[myidx-1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003127 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003128 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003129 else if (strcmp(args[myidx], "peers") == 0) {
3130 myidx++;
Godbach50523162013-12-11 19:48:57 +08003131 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003132 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3133 file, linenum, args[myidx-1]);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Godbach50523162013-12-11 19:48:57 +08003136 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003137 curproxy->table.peers.name = strdup(args[myidx++]);
3138 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003139 else if (strcmp(args[myidx], "expire") == 0) {
3140 myidx++;
3141 if (!*(args[myidx])) {
3142 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3143 file, linenum, args[myidx-1]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3148 if (err) {
3149 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3150 file, linenum, *err, args[myidx-1]);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003155 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003156 }
3157 else if (strcmp(args[myidx], "nopurge") == 0) {
3158 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003159 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 }
3161 else if (strcmp(args[myidx], "type") == 0) {
3162 myidx++;
3163 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3164 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3165 file, linenum, args[myidx]);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
3168 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003169 /* myidx already points to next arg */
3170 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003171 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003172 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003173 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003174
3175 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003176 nw = args[myidx];
3177 while (*nw) {
3178 /* the "store" keyword supports a comma-separated list */
3179 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003180 sa = NULL; /* store arg */
3181 while (*nw && *nw != ',') {
3182 if (*nw == '(') {
3183 *nw = 0;
3184 sa = ++nw;
3185 while (*nw != ')') {
3186 if (!*nw) {
3187 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3188 file, linenum, args[0], cw);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
3191 }
3192 nw++;
3193 }
3194 *nw = '\0';
3195 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003196 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003197 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003198 if (*nw)
3199 *nw++ = '\0';
3200 type = stktable_get_data_type(cw);
3201 if (type < 0) {
3202 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3203 file, linenum, args[0], cw);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
Willy Tarreauac782882010-06-20 10:41:54 +02003207
3208 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3209 switch (err) {
3210 case PE_NONE: break;
3211 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003212 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3213 file, linenum, args[0], cw);
3214 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003215 break;
3216
3217 case PE_ARG_MISSING:
3218 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3219 file, linenum, args[0], cw);
3220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
3222
3223 case PE_ARG_NOT_USED:
3224 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3225 file, linenum, args[0], cw);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228
3229 default:
3230 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3231 file, linenum, args[0], cw);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003234 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003235 }
3236 myidx++;
3237 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003238 else {
3239 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3240 file, linenum, args[myidx]);
3241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003243 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003244 }
3245
3246 if (!curproxy->table.size) {
3247 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3248 file, linenum);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 if (curproxy->table.type == (unsigned int)-1) {
3254 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3255 file, linenum);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259 }
3260 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003261 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003262 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 int myidx = 0;
3264 const char *name = NULL;
3265 int flags;
3266
3267 if (curproxy == &defproxy) {
3268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271 }
3272
3273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3274 err_code |= ERR_WARN;
3275 goto out;
3276 }
3277
3278 myidx++;
3279 if ((strcmp(args[myidx], "store") == 0) ||
3280 (strcmp(args[myidx], "store-request") == 0)) {
3281 myidx++;
3282 flags = STK_IS_STORE;
3283 }
3284 else if (strcmp(args[myidx], "store-response") == 0) {
3285 myidx++;
3286 flags = STK_IS_STORE | STK_ON_RSP;
3287 }
3288 else if (strcmp(args[myidx], "match") == 0) {
3289 myidx++;
3290 flags = STK_IS_MATCH;
3291 }
3292 else if (strcmp(args[myidx], "on") == 0) {
3293 myidx++;
3294 flags = STK_IS_MATCH | STK_IS_STORE;
3295 }
3296 else {
3297 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
3301
3302 if (*(args[myidx]) == 0) {
3303 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
3306 }
3307
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003308 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003309 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003310 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003311 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
3315
3316 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003317 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3318 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3319 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003320 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003321 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003322 goto out;
3323 }
3324 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003325 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3326 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3327 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003328 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003329 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003330 goto out;
3331 }
3332 }
3333
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003334 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003335 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003336
Emeric Brunb982a3d2010-01-04 15:45:53 +01003337 if (strcmp(args[myidx], "table") == 0) {
3338 myidx++;
3339 name = args[myidx++];
3340 }
3341
Willy Tarreauef6494c2010-01-28 17:12:36 +01003342 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003343 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3344 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3345 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003346 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003347 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003348 goto out;
3349 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003350 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003351 else if (*(args[myidx])) {
3352 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3353 file, linenum, args[0], args[myidx]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003355 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003356 goto out;
3357 }
Emeric Brun97679e72010-09-23 17:56:44 +02003358 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003359 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003360 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003361 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003362
Emeric Brunb982a3d2010-01-04 15:45:53 +01003363 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3364 rule->cond = cond;
3365 rule->expr = expr;
3366 rule->flags = flags;
3367 rule->table.name = name ? strdup(name) : NULL;
3368 LIST_INIT(&rule->list);
3369 if (flags & STK_ON_RSP)
3370 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3371 else
3372 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 else if (!strcmp(args[0], "stats")) {
3375 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3376 curproxy->uri_auth = NULL; /* we must detach from the default config */
3377
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003378 if (!*args[1]) {
3379 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003380 } else if (!strcmp(args[1], "admin")) {
3381 struct stats_admin_rule *rule;
3382
3383 if (curproxy == &defproxy) {
3384 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3390 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3391 err_code |= ERR_ALERT | ERR_ABORT;
3392 goto out;
3393 }
3394
3395 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3396 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3397 file, linenum, args[0], args[1]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003401 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3402 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3403 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
3406 }
3407
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003408 err_code |= warnif_cond_conflicts(cond,
3409 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3410 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003411
3412 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3413 rule->cond = cond;
3414 LIST_INIT(&rule->list);
3415 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 } else if (!strcmp(args[1], "uri")) {
3417 if (*(args[2]) == 0) {
3418 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3422 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_ABORT;
3424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 }
3426 } else if (!strcmp(args[1], "realm")) {
3427 if (*(args[2]) == 0) {
3428 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_ABORT;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003436 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003437 unsigned interval;
3438
3439 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3440 if (err) {
3441 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3442 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003445 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_ABORT;
3448 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003449 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003450 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003451 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003452
3453 if (curproxy == &defproxy) {
3454 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458
3459 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3460 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3461 err_code |= ERR_ALERT | ERR_ABORT;
3462 goto out;
3463 }
3464
Willy Tarreauff011f22011-01-06 17:51:27 +01003465 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3466 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003467 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3468 file, linenum, args[0]);
3469 err_code |= ERR_WARN;
3470 }
3471
Willy Tarreauff011f22011-01-06 17:51:27 +01003472 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003473
Willy Tarreauff011f22011-01-06 17:51:27 +01003474 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003475 err_code |= ERR_ALERT | ERR_ABORT;
3476 goto out;
3477 }
3478
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003479 err_code |= warnif_cond_conflicts(rule->cond,
3480 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3481 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003482 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003483
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 } else if (!strcmp(args[1], "auth")) {
3485 if (*(args[2]) == 0) {
3486 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3490 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_ABORT;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494 } else if (!strcmp(args[1], "scope")) {
3495 if (*(args[2]) == 0) {
3496 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3500 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_ABORT;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
3504 } else if (!strcmp(args[1], "enable")) {
3505 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3506 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_ABORT;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003510 } else if (!strcmp(args[1], "hide-version")) {
3511 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3512 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_ABORT;
3514 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003515 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003516 } else if (!strcmp(args[1], "show-legends")) {
3517 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3518 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3519 err_code |= ERR_ALERT | ERR_ABORT;
3520 goto out;
3521 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003522 } else if (!strcmp(args[1], "show-node")) {
3523
3524 if (*args[2]) {
3525 int i;
3526 char c;
3527
3528 for (i=0; args[2][i]; i++) {
3529 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003530 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3531 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003532 break;
3533 }
3534
3535 if (!i || args[2][i]) {
3536 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3537 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3538 file, linenum, args[0], args[1]);
3539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
3541 }
3542 }
3543
3544 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3545 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3546 err_code |= ERR_ALERT | ERR_ABORT;
3547 goto out;
3548 }
3549 } else if (!strcmp(args[1], "show-desc")) {
3550 char *desc = NULL;
3551
3552 if (*args[2]) {
3553 int i, len=0;
3554 char *d;
3555
Willy Tarreau348acfe2014-04-14 15:00:39 +02003556 for (i = 2; *args[i]; i++)
3557 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003558
3559 desc = d = (char *)calloc(1, len);
3560
Willy Tarreau348acfe2014-04-14 15:00:39 +02003561 d += snprintf(d, desc + len - d, "%s", args[2]);
3562 for (i = 3; *args[i]; i++)
3563 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003564 }
3565
3566 if (!*args[2] && !global.desc)
3567 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3568 file, linenum, args[1]);
3569 else {
3570 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3571 free(desc);
3572 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3573 err_code |= ERR_ALERT | ERR_ABORT;
3574 goto out;
3575 }
3576 free(desc);
3577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003579stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003580 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 +01003581 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 }
3585 }
3586 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003587 int optnum;
3588
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003589 if (*(args[1]) == '\0') {
3590 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003595
3596 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3597 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003598 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3599 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3600 file, linenum, cfg_opts[optnum].name);
3601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
3603 }
Willy Tarreau93893792009-07-23 13:19:11 +02003604 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3605 err_code |= ERR_WARN;
3606 goto out;
3607 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003608
Willy Tarreau3842f002009-06-14 11:39:52 +02003609 curproxy->no_options &= ~cfg_opts[optnum].val;
3610 curproxy->options &= ~cfg_opts[optnum].val;
3611
3612 switch (kwm) {
3613 case KWM_STD:
3614 curproxy->options |= cfg_opts[optnum].val;
3615 break;
3616 case KWM_NO:
3617 curproxy->no_options |= cfg_opts[optnum].val;
3618 break;
3619 case KWM_DEF: /* already cleared */
3620 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003621 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003622
Willy Tarreau93893792009-07-23 13:19:11 +02003623 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003624 }
3625 }
3626
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003627 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3628 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003629 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3630 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3631 file, linenum, cfg_opts2[optnum].name);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
Willy Tarreau93893792009-07-23 13:19:11 +02003635 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3636 err_code |= ERR_WARN;
3637 goto out;
3638 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003639
Willy Tarreau3842f002009-06-14 11:39:52 +02003640 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3641 curproxy->options2 &= ~cfg_opts2[optnum].val;
3642
3643 switch (kwm) {
3644 case KWM_STD:
3645 curproxy->options2 |= cfg_opts2[optnum].val;
3646 break;
3647 case KWM_NO:
3648 curproxy->no_options2 |= cfg_opts2[optnum].val;
3649 break;
3650 case KWM_DEF: /* already cleared */
3651 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003652 }
Willy Tarreau93893792009-07-23 13:19:11 +02003653 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003654 }
3655 }
3656
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003657 /* HTTP options override each other. They can be cancelled using
3658 * "no option xxx" which only switches to default mode if the mode
3659 * was this one (useful for cancelling options set in defaults
3660 * sections).
3661 */
3662 if (strcmp(args[1], "httpclose") == 0) {
3663 if (kwm == KWM_STD) {
3664 curproxy->options &= ~PR_O_HTTP_MODE;
3665 curproxy->options |= PR_O_HTTP_PCL;
3666 goto out;
3667 }
3668 else if (kwm == KWM_NO) {
3669 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3670 curproxy->options &= ~PR_O_HTTP_MODE;
3671 goto out;
3672 }
3673 }
3674 else if (strcmp(args[1], "forceclose") == 0) {
3675 if (kwm == KWM_STD) {
3676 curproxy->options &= ~PR_O_HTTP_MODE;
3677 curproxy->options |= PR_O_HTTP_FCL;
3678 goto out;
3679 }
3680 else if (kwm == KWM_NO) {
3681 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3682 curproxy->options &= ~PR_O_HTTP_MODE;
3683 goto out;
3684 }
3685 }
3686 else if (strcmp(args[1], "http-server-close") == 0) {
3687 if (kwm == KWM_STD) {
3688 curproxy->options &= ~PR_O_HTTP_MODE;
3689 curproxy->options |= PR_O_HTTP_SCL;
3690 goto out;
3691 }
3692 else if (kwm == KWM_NO) {
3693 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3694 curproxy->options &= ~PR_O_HTTP_MODE;
3695 goto out;
3696 }
3697 }
3698 else if (strcmp(args[1], "http-keep-alive") == 0) {
3699 if (kwm == KWM_STD) {
3700 curproxy->options &= ~PR_O_HTTP_MODE;
3701 curproxy->options |= PR_O_HTTP_KAL;
3702 goto out;
3703 }
3704 else if (kwm == KWM_NO) {
3705 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3706 curproxy->options &= ~PR_O_HTTP_MODE;
3707 goto out;
3708 }
3709 }
3710 else if (strcmp(args[1], "http-tunnel") == 0) {
3711 if (kwm == KWM_STD) {
3712 curproxy->options &= ~PR_O_HTTP_MODE;
3713 curproxy->options |= PR_O_HTTP_TUN;
3714 goto out;
3715 }
3716 else if (kwm == KWM_NO) {
3717 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3718 curproxy->options &= ~PR_O_HTTP_MODE;
3719 goto out;
3720 }
3721 }
3722
Willy Tarreau3842f002009-06-14 11:39:52 +02003723 if (kwm != KWM_STD) {
3724 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003725 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003728 }
3729
Emeric Brun3a058f32009-06-30 18:26:00 +02003730 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003731 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003733 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003734 if (*(args[2]) != '\0') {
3735 if (!strcmp(args[2], "clf")) {
3736 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003737 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003738 } else {
3739 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003742 }
3743 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003744 if (curproxy->conf.logformat_string != default_http_log_format &&
3745 curproxy->conf.logformat_string != default_tcp_log_format &&
3746 curproxy->conf.logformat_string != clf_http_log_format)
3747 free(curproxy->conf.logformat_string);
3748 curproxy->conf.logformat_string = logformat;
3749
3750 free(curproxy->conf.lfs_file);
3751 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3752 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003753 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003754 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003756 if (curproxy->conf.logformat_string != default_http_log_format &&
3757 curproxy->conf.logformat_string != default_tcp_log_format &&
3758 curproxy->conf.logformat_string != clf_http_log_format)
3759 free(curproxy->conf.logformat_string);
3760 curproxy->conf.logformat_string = default_tcp_log_format;
3761
3762 free(curproxy->conf.lfs_file);
3763 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3764 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 else if (!strcmp(args[1], "tcpka")) {
3767 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003768 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003770
3771 if (curproxy->cap & PR_CAP_FE)
3772 curproxy->options |= PR_O_TCP_CLI_KA;
3773 if (curproxy->cap & PR_CAP_BE)
3774 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
3776 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003777 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_WARN;
3779
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003781 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003782 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003783 curproxy->options2 &= ~PR_O2_CHK_ANY;
3784 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 if (!*args[2]) { /* no argument */
3786 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3787 curproxy->check_len = strlen(DEF_CHECK_REQ);
3788 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003789 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 curproxy->check_req = (char *)malloc(reqlen);
3791 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003792 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003794 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 if (*args[4])
3796 reqlen += strlen(args[4]);
3797 else
3798 reqlen += strlen("HTTP/1.0");
3799
3800 curproxy->check_req = (char *)malloc(reqlen);
3801 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003802 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003804 }
3805 else if (!strcmp(args[1], "ssl-hello-chk")) {
3806 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003807 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003809
Willy Tarreaua534fea2008-08-03 12:19:50 +02003810 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003811 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003812 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003813 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
Willy Tarreau23677902007-05-08 23:50:35 +02003815 else if (!strcmp(args[1], "smtpchk")) {
3816 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003817 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003818 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003819 curproxy->options2 &= ~PR_O2_CHK_ANY;
3820 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003821
3822 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3823 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3824 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3825 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3826 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3827 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3828 curproxy->check_req = (char *)malloc(reqlen);
3829 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3830 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3831 } else {
3832 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3833 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3834 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3835 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3836 }
3837 }
3838 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003839 else if (!strcmp(args[1], "pgsql-check")) {
3840 /* use PostgreSQL request to check servers' health */
3841 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3842 err_code |= ERR_WARN;
3843
3844 free(curproxy->check_req);
3845 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003846 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003847 curproxy->options2 |= PR_O2_PGSQL_CHK;
3848
3849 if (*(args[2])) {
3850 int cur_arg = 2;
3851
3852 while (*(args[cur_arg])) {
3853 if (strcmp(args[cur_arg], "user") == 0) {
3854 char * packet;
3855 uint32_t packet_len;
3856 uint32_t pv;
3857
3858 /* suboption header - needs additional argument for it */
3859 if (*(args[cur_arg+1]) == 0) {
3860 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3861 file, linenum, args[0], args[1], args[cur_arg]);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865
3866 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3867 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3868 pv = htonl(0x30000); /* protocol version 3.0 */
3869
3870 packet = (char*) calloc(1, packet_len);
3871
3872 memcpy(packet + 4, &pv, 4);
3873
3874 /* copy "user" */
3875 memcpy(packet + 8, "user", 4);
3876
3877 /* copy username */
3878 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3879
3880 free(curproxy->check_req);
3881 curproxy->check_req = packet;
3882 curproxy->check_len = packet_len;
3883
3884 packet_len = htonl(packet_len);
3885 memcpy(packet, &packet_len, 4);
3886 cur_arg += 2;
3887 } else {
3888 /* unknown suboption - catchall */
3889 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3890 file, linenum, args[0], args[1]);
3891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894 } /* end while loop */
3895 }
3896 }
3897
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003898 else if (!strcmp(args[1], "redis-check")) {
3899 /* use REDIS PING request to check servers' health */
3900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3901 err_code |= ERR_WARN;
3902
3903 free(curproxy->check_req);
3904 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003905 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003906 curproxy->options2 |= PR_O2_REDIS_CHK;
3907
3908 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3909 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3910 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3911 }
3912
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003913 else if (!strcmp(args[1], "mysql-check")) {
3914 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3916 err_code |= ERR_WARN;
3917
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003918 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003919 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003920 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003921 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003922
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003923 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003924 * const char mysql40_client_auth_pkt[] = {
3925 * "\x0e\x00\x00" // packet length
3926 * "\x01" // packet number
3927 * "\x00\x00" // client capabilities
3928 * "\x00\x00\x01" // max packet
3929 * "haproxy\x00" // username (null terminated string)
3930 * "\x00" // filler (always 0x00)
3931 * "\x01\x00\x00" // packet length
3932 * "\x00" // packet number
3933 * "\x01" // COM_QUIT command
3934 * };
3935 */
3936
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003937 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3938 * const char mysql41_client_auth_pkt[] = {
3939 * "\x0e\x00\x00\" // packet length
3940 * "\x01" // packet number
3941 * "\x00\x00\x00\x00" // client capabilities
3942 * "\x00\x00\x00\x01" // max packet
3943 * "\x21" // character set (UTF-8)
3944 * char[23] // All zeroes
3945 * "haproxy\x00" // username (null terminated string)
3946 * "\x00" // filler (always 0x00)
3947 * "\x01\x00\x00" // packet length
3948 * "\x00" // packet number
3949 * "\x01" // COM_QUIT command
3950 * };
3951 */
3952
3953
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003954 if (*(args[2])) {
3955 int cur_arg = 2;
3956
3957 while (*(args[cur_arg])) {
3958 if (strcmp(args[cur_arg], "user") == 0) {
3959 char *mysqluser;
3960 int packetlen, reqlen, userlen;
3961
3962 /* suboption header - needs additional argument for it */
3963 if (*(args[cur_arg+1]) == 0) {
3964 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3965 file, linenum, args[0], args[1], args[cur_arg]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 mysqluser = args[cur_arg + 1];
3970 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003971
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003972 if (*(args[cur_arg+2])) {
3973 if (!strcmp(args[cur_arg+2], "post-41")) {
3974 packetlen = userlen + 7 + 27;
3975 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003976
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003977 free(curproxy->check_req);
3978 curproxy->check_req = (char *)calloc(1, reqlen);
3979 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003980
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003981 snprintf(curproxy->check_req, 4, "%c%c%c",
3982 ((unsigned char) packetlen & 0xff),
3983 ((unsigned char) (packetlen >> 8) & 0xff),
3984 ((unsigned char) (packetlen >> 16) & 0xff));
3985
3986 curproxy->check_req[3] = 1;
3987 curproxy->check_req[5] = 130;
3988 curproxy->check_req[11] = 1;
3989 curproxy->check_req[12] = 33;
3990 memcpy(&curproxy->check_req[36], mysqluser, userlen);
3991 curproxy->check_req[36 + userlen + 1 + 1] = 1;
3992 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
3993 cur_arg += 3;
3994 } else {
3995 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
3999 } else {
4000 packetlen = userlen + 7;
4001 reqlen = packetlen + 9;
4002
4003 free(curproxy->check_req);
4004 curproxy->check_req = (char *)calloc(1, reqlen);
4005 curproxy->check_len = reqlen;
4006
4007 snprintf(curproxy->check_req, 4, "%c%c%c",
4008 ((unsigned char) packetlen & 0xff),
4009 ((unsigned char) (packetlen >> 8) & 0xff),
4010 ((unsigned char) (packetlen >> 16) & 0xff));
4011
4012 curproxy->check_req[3] = 1;
4013 curproxy->check_req[5] = 128;
4014 curproxy->check_req[8] = 1;
4015 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4016 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4017 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4018 cur_arg += 2;
4019 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004020 } else {
4021 /* unknown suboption - catchall */
4022 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4023 file, linenum, args[0], args[1]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027 } /* end while loop */
4028 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004029 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004030 else if (!strcmp(args[1], "ldap-check")) {
4031 /* use LDAP request to check servers' health */
4032 free(curproxy->check_req);
4033 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004034 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004035 curproxy->options2 |= PR_O2_LDAP_CHK;
4036
4037 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4038 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4039 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4040 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004041 else if (!strcmp(args[1], "tcp-check")) {
4042 /* use raw TCPCHK send/expect to check servers' health */
4043 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4044 err_code |= ERR_WARN;
4045
4046 free(curproxy->check_req);
4047 curproxy->check_req = NULL;
4048 curproxy->options2 &= ~PR_O2_CHK_ANY;
4049 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4050 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004051 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004052 int cur_arg;
4053
4054 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4055 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004056 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004057
Willy Tarreau87cf5142011-08-19 22:57:24 +02004058 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004059
4060 free(curproxy->fwdfor_hdr_name);
4061 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4062 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4063
4064 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4065 cur_arg = 2;
4066 while (*(args[cur_arg])) {
4067 if (!strcmp(args[cur_arg], "except")) {
4068 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004069 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004070 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4071 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004074 }
4075 /* flush useless bits */
4076 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004077 cur_arg += 2;
4078 } else if (!strcmp(args[cur_arg], "header")) {
4079 /* suboption header - needs additional argument for it */
4080 if (*(args[cur_arg+1]) == 0) {
4081 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4082 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004085 }
4086 free(curproxy->fwdfor_hdr_name);
4087 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4088 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4089 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004090 } else if (!strcmp(args[cur_arg], "if-none")) {
4091 curproxy->options &= ~PR_O_FF_ALWAYS;
4092 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004093 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004094 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004095 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004096 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004099 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004100 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004101 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004102 else if (!strcmp(args[1], "originalto")) {
4103 int cur_arg;
4104
4105 /* insert x-original-to field, but not for the IP address listed as an except.
4106 * set default options (ie: bitfield, header name, etc)
4107 */
4108
4109 curproxy->options |= PR_O_ORGTO;
4110
4111 free(curproxy->orgto_hdr_name);
4112 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4113 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4114
Willy Tarreau87cf5142011-08-19 22:57:24 +02004115 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004116 cur_arg = 2;
4117 while (*(args[cur_arg])) {
4118 if (!strcmp(args[cur_arg], "except")) {
4119 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004120 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 +02004121 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4122 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004125 }
4126 /* flush useless bits */
4127 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4128 cur_arg += 2;
4129 } else if (!strcmp(args[cur_arg], "header")) {
4130 /* suboption header - needs additional argument for it */
4131 if (*(args[cur_arg+1]) == 0) {
4132 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4133 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004136 }
4137 free(curproxy->orgto_hdr_name);
4138 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4139 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4140 cur_arg += 2;
4141 } else {
4142 /* unknown suboption - catchall */
4143 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004147 }
4148 } /* end while loop */
4149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 else {
4151 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreau93893792009-07-23 13:19:11 +02004155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004157 else if (!strcmp(args[0], "default_backend")) {
4158 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004160
4161 if (*(args[1]) == 0) {
4162 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004165 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004166 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004167 curproxy->defbe.name = strdup(args[1]);
4168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004172
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004173 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4174 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 +01004175 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 /* enable reconnections to dispatch */
4178 curproxy->options |= PR_O_REDISP;
4179 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004180 else if (!strcmp(args[0], "http-check")) {
4181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004183
4184 if (strcmp(args[1], "disable-on-404") == 0) {
4185 /* enable a graceful server shutdown on an HTTP 404 response */
4186 curproxy->options |= PR_O_DISABLE404;
4187 }
Willy Tarreauef781042010-01-27 11:53:01 +01004188 else if (strcmp(args[1], "send-state") == 0) {
4189 /* enable emission of the apparent state of a server in HTTP checks */
4190 curproxy->options2 |= PR_O2_CHK_SNDST;
4191 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004192 else if (strcmp(args[1], "expect") == 0) {
4193 const char *ptr_arg;
4194 int cur_arg;
4195
4196 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4197 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
4202 cur_arg = 2;
4203 /* consider exclamation marks, sole or at the beginning of a word */
4204 while (*(ptr_arg = args[cur_arg])) {
4205 while (*ptr_arg == '!') {
4206 curproxy->options2 ^= PR_O2_EXP_INV;
4207 ptr_arg++;
4208 }
4209 if (*ptr_arg)
4210 break;
4211 cur_arg++;
4212 }
4213 /* now ptr_arg points to the beginning of a word past any possible
4214 * exclamation mark, and cur_arg is the argument which holds this word.
4215 */
4216 if (strcmp(ptr_arg, "status") == 0) {
4217 if (!*(args[cur_arg + 1])) {
4218 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4219 file, linenum, args[0], args[1], ptr_arg);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004224 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004225 curproxy->expect_str = strdup(args[cur_arg + 1]);
4226 }
4227 else if (strcmp(ptr_arg, "string") == 0) {
4228 if (!*(args[cur_arg + 1])) {
4229 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4230 file, linenum, args[0], args[1], ptr_arg);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004235 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004236 curproxy->expect_str = strdup(args[cur_arg + 1]);
4237 }
4238 else if (strcmp(ptr_arg, "rstatus") == 0) {
4239 if (!*(args[cur_arg + 1])) {
4240 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4241 file, linenum, args[0], args[1], ptr_arg);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 }
4245 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004246 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004247 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004248 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004249 free(curproxy->expect_regex);
4250 curproxy->expect_regex = NULL;
4251 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004252 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004253 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4254 error = NULL;
4255 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4256 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4257 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4258 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262 }
4263 else if (strcmp(ptr_arg, "rstring") == 0) {
4264 if (!*(args[cur_arg + 1])) {
4265 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4266 file, linenum, args[0], args[1], ptr_arg);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004271 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004272 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004273 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004274 free(curproxy->expect_regex);
4275 curproxy->expect_regex = NULL;
4276 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004277 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004278 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4279 error = NULL;
4280 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4281 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4282 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4283 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287 }
4288 else {
4289 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4290 file, linenum, args[0], args[1], ptr_arg);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004295 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004296 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 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004299 }
4300 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004301 else if (!strcmp(args[0], "tcp-check")) {
4302 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4303 err_code |= ERR_WARN;
4304
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004305 if (strcmp(args[1], "connect") == 0) {
4306 const char *ptr_arg;
4307 int cur_arg;
4308 struct tcpcheck_rule *tcpcheck;
4309 struct list *l;
4310
4311 /* check if first rule is also a 'connect' action */
4312 l = (struct list *)&curproxy->tcpcheck_rules;
4313 if (l->p != l->n) {
4314 tcpcheck = (struct tcpcheck_rule *)l->n;
4315 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4316 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4317 file, linenum);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321 }
4322
4323 cur_arg = 2;
4324 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4325 tcpcheck->action = TCPCHK_ACT_CONNECT;
4326
4327 /* parsing each parameters to fill up the rule */
4328 while (*(ptr_arg = args[cur_arg])) {
4329 /* tcp port */
4330 if (strcmp(args[cur_arg], "port") == 0) {
4331 if ( (atol(args[cur_arg + 1]) > 65535) ||
4332 (atol(args[cur_arg + 1]) < 1) ){
4333 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4334 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338 tcpcheck->port = atol(args[cur_arg + 1]);
4339 cur_arg += 2;
4340 }
4341 /* send proxy protocol */
4342 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4343 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4344 cur_arg++;
4345 }
4346#ifdef USE_OPENSSL
4347 else if (strcmp(args[cur_arg], "ssl") == 0) {
4348 curproxy->options |= PR_O_TCPCHK_SSL;
4349 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4350 cur_arg++;
4351 }
4352#endif /* USE_OPENSSL */
4353 else {
4354#ifdef USE_OPENSSL
4355 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4356#else /* USE_OPENSSL */
4357 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4358#endif /* USE_OPENSSL */
4359 file, linenum, args[0], args[1], args[cur_arg]);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363
4364 }
4365
4366 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4367 }
4368 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004369 if (! *(args[2]) ) {
4370 /* SEND string expected */
4371 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4372 file, linenum, args[0], args[1], args[2]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 } else {
4376 struct tcpcheck_rule *tcpcheck;
4377
4378 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4379
4380 tcpcheck->action = TCPCHK_ACT_SEND;
4381 tcpcheck->string_len = strlen(args[2]);
4382 tcpcheck->string = strdup(args[2]);
4383 tcpcheck->expect_regex = NULL;
4384
4385 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4386 }
4387 }
4388 else if (strcmp(args[1], "send-binary") == 0) {
4389 if (! *(args[2]) ) {
4390 /* SEND binary string expected */
4391 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4392 file, linenum, args[0], args[1], args[2]);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395 } else {
4396 struct tcpcheck_rule *tcpcheck;
4397 char *err = NULL;
4398
4399 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4400
4401 tcpcheck->action = TCPCHK_ACT_SEND;
4402 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4403 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4404 file, linenum, args[0], args[1], args[2], err);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
4408 tcpcheck->expect_regex = NULL;
4409
4410 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4411 }
4412 }
4413 else if (strcmp(args[1], "expect") == 0) {
4414 const char *ptr_arg;
4415 int cur_arg;
4416 int inverse = 0;
4417
4418 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4419 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423
4424 cur_arg = 2;
4425 /* consider exclamation marks, sole or at the beginning of a word */
4426 while (*(ptr_arg = args[cur_arg])) {
4427 while (*ptr_arg == '!') {
4428 inverse = !inverse;
4429 ptr_arg++;
4430 }
4431 if (*ptr_arg)
4432 break;
4433 cur_arg++;
4434 }
4435 /* now ptr_arg points to the beginning of a word past any possible
4436 * exclamation mark, and cur_arg is the argument which holds this word.
4437 */
4438 if (strcmp(ptr_arg, "binary") == 0) {
4439 if (!*(args[cur_arg + 1])) {
4440 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4441 file, linenum, args[0], args[1], ptr_arg);
4442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
4444 }
4445 struct tcpcheck_rule *tcpcheck;
4446 char *err = NULL;
4447
4448 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4449
4450 tcpcheck->action = TCPCHK_ACT_EXPECT;
4451 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4452 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4453 file, linenum, args[0], args[1], args[2], err);
4454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
4456 }
4457 tcpcheck->expect_regex = NULL;
4458 tcpcheck->inverse = inverse;
4459
4460 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4461 }
4462 else if (strcmp(ptr_arg, "string") == 0) {
4463 if (!*(args[cur_arg + 1])) {
4464 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4465 file, linenum, args[0], args[1], ptr_arg);
4466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
4468 }
4469 struct tcpcheck_rule *tcpcheck;
4470
4471 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4472
4473 tcpcheck->action = TCPCHK_ACT_EXPECT;
4474 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4475 tcpcheck->string = strdup(args[cur_arg + 1]);
4476 tcpcheck->expect_regex = NULL;
4477 tcpcheck->inverse = inverse;
4478
4479 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4480 }
4481 else if (strcmp(ptr_arg, "rstring") == 0) {
4482 if (!*(args[cur_arg + 1])) {
4483 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4484 file, linenum, args[0], args[1], ptr_arg);
4485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
4487 }
4488 struct tcpcheck_rule *tcpcheck;
4489
4490 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4491
4492 tcpcheck->action = TCPCHK_ACT_EXPECT;
4493 tcpcheck->string_len = 0;
4494 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004495 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4496 error = NULL;
4497 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4498 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4499 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4500 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004501 err_code |= ERR_ALERT | ERR_FATAL;
4502 goto out;
4503 }
4504 tcpcheck->inverse = inverse;
4505
4506 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4507 }
4508 else {
4509 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4510 file, linenum, args[0], args[1], ptr_arg);
4511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
4514 }
4515 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004516 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
4519 }
4520 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004521 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004522 if (curproxy == &defproxy) {
4523 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004526 }
4527
Willy Tarreaub80c2302007-11-30 20:51:32 +01004528 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004530
4531 if (strcmp(args[1], "fail") == 0) {
4532 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004533 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004534 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4535 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004538 }
4539
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004540 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4541 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4542 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004545 }
4546 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4547 }
4548 else {
4549 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004552 }
4553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554#ifdef TPROXY
4555 else if (!strcmp(args[0], "transparent")) {
4556 /* enable transparent proxy connections */
4557 curproxy->options |= PR_O_TRANSP;
4558 }
4559#endif
4560 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004563
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 if (*(args[1]) == 0) {
4565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 }
4569 curproxy->maxconn = atol(args[1]);
4570 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004571 else if (!strcmp(args[0], "backlog")) { /* backlog */
4572 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004574
4575 if (*(args[1]) == 0) {
4576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004579 }
4580 curproxy->backlog = atol(args[1]);
4581 }
Willy Tarreau86034312006-12-29 00:10:33 +01004582 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004585
Willy Tarreau86034312006-12-29 00:10:33 +01004586 if (*(args[1]) == 0) {
4587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004590 }
4591 curproxy->fullconn = atol(args[1]);
4592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4594 if (*(args[1]) == 0) {
4595 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004599 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4600 if (err) {
4601 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4602 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004605 }
4606 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 }
4608 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004609 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004610 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004611 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004612
Willy Tarreaubaaee002006-06-26 02:48:02 +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 Tarreaubaaee002006-06-26 02:48:02 +02004617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004618 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004620
Willy Tarreau902636f2013-03-10 19:44:48 +01004621 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004622 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004623 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004625 goto out;
4626 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004627
4628 proto = protocol_by_family(sk->ss_family);
4629 if (!proto || !proto->connect) {
4630 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4631 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635
4636 if (port1 != port2) {
4637 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4638 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004642
4643 if (!port1) {
4644 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4645 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004649
Willy Tarreaud5191e72010-02-09 20:50:45 +01004650 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004651 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
4653 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004656
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004657 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4658 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004663 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004664 /**
4665 * The syntax for hash-type config element is
4666 * hash-type {map-based|consistent} [[<algo>] avalanche]
4667 *
4668 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4669 */
4670 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004671
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004672 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4673 err_code |= ERR_WARN;
4674
4675 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004676 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4677 }
4678 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004679 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4680 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004681 else if (strcmp(args[1], "avalanche") == 0) {
4682 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]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004685 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004686 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004687 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
Bhaskar98634f02013-10-29 23:30:51 -04004691
4692 /* set the hash function to use */
4693 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004694 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004695 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004696
4697 /* if consistent with no argument, then avalanche modifier is also applied */
4698 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4699 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004700 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004701 /* set the hash function */
4702 if (!strcmp(args[2], "sdbm")) {
4703 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4704 }
4705 else if (!strcmp(args[2], "djb2")) {
4706 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004707 } else if (!strcmp(args[2], "wt6")) {
4708 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004709 }
4710 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004711 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 -05004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714 }
4715
4716 /* set the hash modifier */
4717 if (!strcmp(args[3], "avalanche")) {
4718 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4719 }
4720 else if (*args[3]) {
4721 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004725 }
William Lallemanda73203e2012-03-12 12:48:57 +01004726 }
William Lallemanda73203e2012-03-12 12:48:57 +01004727 else if (strcmp(args[0], "unique-id-format") == 0) {
4728 if (!*(args[1])) {
4729 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
4732 }
William Lallemand3203ff42012-11-11 17:30:56 +01004733 if (*(args[2])) {
4734 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004738 free(curproxy->conf.uniqueid_format_string);
4739 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004740
Willy Tarreau62a61232013-04-12 18:13:46 +02004741 free(curproxy->conf.uif_file);
4742 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4743 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004744 }
William Lallemanda73203e2012-03-12 12:48:57 +01004745
4746 else if (strcmp(args[0], "unique-id-header") == 0) {
4747 if (!*(args[1])) {
4748 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
4752 free(curproxy->header_unique_id);
4753 curproxy->header_unique_id = strdup(args[1]);
4754 }
4755
William Lallemand723b73a2012-02-08 16:37:49 +01004756 else if (strcmp(args[0], "log-format") == 0) {
4757 if (!*(args[1])) {
4758 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
William Lallemand3203ff42012-11-11 17:30:56 +01004762 if (*(args[2])) {
4763 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
4766 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004767
Willy Tarreau62a61232013-04-12 18:13:46 +02004768 if (curproxy->conf.logformat_string != default_http_log_format &&
4769 curproxy->conf.logformat_string != default_tcp_log_format &&
4770 curproxy->conf.logformat_string != clf_http_log_format)
4771 free(curproxy->conf.logformat_string);
4772 curproxy->conf.logformat_string = strdup(args[1]);
4773
4774 free(curproxy->conf.lfs_file);
4775 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4776 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004777
4778 /* get a chance to improve log-format error reporting by
4779 * reporting the correct line-number when possible.
4780 */
4781 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4782 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4783 file, linenum, curproxy->id);
4784 err_code |= ERR_WARN;
4785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 }
William Lallemand723b73a2012-02-08 16:37:49 +01004787
William Lallemand0f99e342011-10-12 17:50:54 +02004788 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4789 /* delete previous herited or defined syslog servers */
4790 struct logsrv *back;
4791
4792 if (*(args[1]) != 0) {
4793 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797
William Lallemand723b73a2012-02-08 16:37:49 +01004798 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4799 LIST_DEL(&tmplogsrv->list);
4800 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004801 }
4802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004804 struct logsrv *logsrv;
4805
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004807 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004808 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004809 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004810 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004811 LIST_INIT(&node->list);
4812 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
4815 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004816 struct sockaddr_storage *sk;
4817 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004818 int arg = 0;
4819 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004820
4821 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004823 /* just after the address, a length may be specified */
4824 if (strcmp(args[arg+2], "len") == 0) {
4825 len = atoi(args[arg+3]);
4826 if (len < 80 || len > 65535) {
4827 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4828 file, linenum, args[arg+3]);
4829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
4831 }
4832 logsrv->maxlen = len;
4833
4834 /* skip these two args */
4835 arg += 2;
4836 }
4837 else
4838 logsrv->maxlen = MAX_SYSLOG_LEN;
4839
4840 if (logsrv->maxlen > global.max_syslog_len) {
4841 global.max_syslog_len = logsrv->maxlen;
4842 logline = realloc(logline, global.max_syslog_len + 1);
4843 }
4844
4845 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004846 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004847 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
4852
William Lallemand0f99e342011-10-12 17:50:54 +02004853 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004854 if (*(args[arg+3])) {
4855 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004856 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004857 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 }
4862 }
4863
William Lallemand0f99e342011-10-12 17:50:54 +02004864 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004865 if (*(args[arg+4])) {
4866 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004867 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004868 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004872 }
4873 }
4874
Willy Tarreau902636f2013-03-10 19:44:48 +01004875 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004876 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004877 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004879 goto out;
4880 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004881
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004882 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004883
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004884 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004885 if (port1 != port2) {
4886 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4887 file, linenum, args[0], args[1]);
4888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
4891
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004892 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004893 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
William Lallemand0f99e342011-10-12 17:50:54 +02004895
4896 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
4898 else {
4899 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4900 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904 }
4905 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004906 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004907 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004908 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004909 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004910
Willy Tarreau977b8e42006-12-29 14:19:17 +01004911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004913
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004915 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4916 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004920
4921 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004922 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4923 free(curproxy->conn_src.iface_name);
4924 curproxy->conn_src.iface_name = NULL;
4925 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004926
Willy Tarreau902636f2013-03-10 19:44:48 +01004927 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004928 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004929 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004930 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004932 goto out;
4933 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004934
4935 proto = protocol_by_family(sk->ss_family);
4936 if (!proto || !proto->connect) {
4937 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004938 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
4941 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004942
4943 if (port1 != port2) {
4944 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4945 file, linenum, args[0], args[1]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
4949
Willy Tarreauef9a3602012-12-08 22:29:20 +01004950 curproxy->conn_src.source_addr = *sk;
4951 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004952
4953 cur_arg = 2;
4954 while (*(args[cur_arg])) {
4955 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004956#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4957#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004958 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4960 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004963 }
4964#endif
4965 if (!*args[cur_arg + 1]) {
4966 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4967 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004970 }
4971
4972 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004973 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4974 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004976 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4977 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004978 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4979 char *name, *end;
4980
4981 name = args[cur_arg+1] + 7;
4982 while (isspace(*name))
4983 name++;
4984
4985 end = name;
4986 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4987 end++;
4988
Willy Tarreauef9a3602012-12-08 22:29:20 +01004989 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4990 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4991 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4992 curproxy->conn_src.bind_hdr_len = end - name;
4993 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4994 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4995 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004996
4997 /* now look for an occurrence number */
4998 while (isspace(*end))
4999 end++;
5000 if (*end == ',') {
5001 end++;
5002 name = end;
5003 if (*end == '-')
5004 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005005 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005006 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005007 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005008 }
5009
Willy Tarreauef9a3602012-12-08 22:29:20 +01005010 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005011 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5012 " occurrences values smaller than %d.\n",
5013 file, linenum, MAX_HDR_HISTORY);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005018 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005019
Willy Tarreau902636f2013-03-10 19:44:48 +01005020 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005021 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005022 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005023 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005024 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005025 goto out;
5026 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005027
5028 proto = protocol_by_family(sk->ss_family);
5029 if (!proto || !proto->connect) {
5030 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5031 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005035
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005036 if (port1 != port2) {
5037 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5038 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005042 curproxy->conn_src.tproxy_addr = *sk;
5043 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005044 }
5045 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005046#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005047 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005048#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049#else /* no TPROXY support */
5050 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005051 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#endif
5055 cur_arg += 2;
5056 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005057 }
5058
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005059 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5060#ifdef SO_BINDTODEVICE
5061 if (!*args[cur_arg + 1]) {
5062 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005067 free(curproxy->conn_src.iface_name);
5068 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5069 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005070 global.last_checks |= LSTCHK_NETADM;
5071#else
5072 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5073 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005076#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005077 cur_arg += 2;
5078 continue;
5079 }
5080 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005081 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005084 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005086 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5087 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5088 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005093 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099
5100 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005101 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005102 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
5106 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005108 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005109 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
5113 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005115 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005116 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
5120 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005122 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005123 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005129 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005130 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005134 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005136 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005137 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005139 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005140 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005141 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005143 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005144 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005147
5148 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5149 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 +01005150 }
5151 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005157
5158 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5159 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 +01005160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168
5169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005170 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005171 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005177 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
5182 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005184 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
5189 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005191 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005192 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
5196 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005198 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005199 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005203 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005205 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005206 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005208 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005211 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005212
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 if (curproxy == &defproxy) {
5214 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005218 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 if (*(args[1]) == 0) {
5222 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005226
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005227 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005228 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5229 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5230 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
5233 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005234 err_code |= warnif_cond_conflicts(cond,
5235 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5236 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005237 }
5238 else if (*args[2]) {
5239 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5240 file, linenum, args[0], args[2]);
5241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
5244
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005245 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005246 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005247 wl->s = strdup(args[1]);
5248 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005249 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
5251 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005258
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005260 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005261 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 }
5265 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005267 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005268 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
5272 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005274 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005275 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
5279 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
5286
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005288 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005289 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005295 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005296 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005302 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005303 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
5307 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005308 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005309
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 if (curproxy == &defproxy) {
5311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005315 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 if (*(args[1]) == 0) {
5319 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 }
5323
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005324 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005325 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5326 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5327 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
5330 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005331 err_code |= warnif_cond_conflicts(cond,
5332 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5333 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005334 }
5335 else if (*args[2]) {
5336 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5337 file, linenum, args[0], args[2]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005342 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005343 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005344 wl->s = strdup(args[1]);
5345 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347 else if (!strcmp(args[0], "errorloc") ||
5348 !strcmp(args[0], "errorloc302") ||
5349 !strcmp(args[0], "errorloc303")) { /* error location */
5350 int errnum, errlen;
5351 char *err;
5352
Willy Tarreau977b8e42006-12-29 14:19:17 +01005353 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005357 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361
5362 errnum = atol(args[1]);
5363 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005364 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5365 err = malloc(errlen);
5366 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005368 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5369 err = malloc(errlen);
5370 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372
Willy Tarreau0f772532006-12-23 20:51:41 +01005373 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5374 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005375 chunk_destroy(&curproxy->errmsg[rc]);
5376 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005377 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005380
5381 if (rc >= HTTP_ERR_SIZE) {
5382 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5383 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 free(err);
5385 }
5386 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005387 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5388 int errnum, errlen, fd;
5389 char *err;
5390 struct stat stat;
5391
5392 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005393 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005394
5395 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005396 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005399 }
5400
5401 fd = open(args[2], O_RDONLY);
5402 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5403 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5404 file, linenum, args[2], args[1]);
5405 if (fd >= 0)
5406 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005409 }
5410
Willy Tarreau27a674e2009-08-17 07:23:33 +02005411 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005412 errlen = stat.st_size;
5413 } else {
5414 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005415 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005417 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005418 }
5419
5420 err = malloc(errlen); /* malloc() must succeed during parsing */
5421 errnum = read(fd, err, errlen);
5422 if (errnum != errlen) {
5423 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5424 file, linenum, args[2], args[1]);
5425 close(fd);
5426 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005429 }
5430 close(fd);
5431
5432 errnum = atol(args[1]);
5433 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5434 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005435 chunk_destroy(&curproxy->errmsg[rc]);
5436 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005437 break;
5438 }
5439 }
5440
5441 if (rc >= HTTP_ERR_SIZE) {
5442 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5443 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005444 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005445 free(err);
5446 }
5447 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005448 else if (!strcmp(args[0], "compression")) {
5449 struct comp *comp;
5450 if (curproxy->comp == NULL) {
5451 comp = calloc(1, sizeof(struct comp));
5452 curproxy->comp = comp;
5453 } else {
5454 comp = curproxy->comp;
5455 }
5456
5457 if (!strcmp(args[1], "algo")) {
5458 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005459 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005460
William Lallemand82fe75c2012-10-23 10:25:10 +02005461 cur_arg = 2;
5462 if (!*args[cur_arg]) {
5463 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5464 file, linenum, args[0]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
5468 while (*(args[cur_arg])) {
5469 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5470 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5471 file, linenum, args[0], args[cur_arg]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
William Lallemand552df672012-11-07 13:21:47 +01005475 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5476 curproxy->comp->algos->end(&ctx);
5477 } else {
5478 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5479 file, linenum, args[0], args[cur_arg]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005483 cur_arg ++;
5484 continue;
5485 }
5486 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005487 else if (!strcmp(args[1], "offload")) {
5488 comp->offload = 1;
5489 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005490 else if (!strcmp(args[1], "type")) {
5491 int cur_arg;
5492 cur_arg = 2;
5493 if (!*args[cur_arg]) {
5494 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5495 file, linenum, args[0]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499 while (*(args[cur_arg])) {
5500 comp_append_type(comp, args[cur_arg]);
5501 cur_arg ++;
5502 continue;
5503 }
5504 }
5505 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005506 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005507 file, linenum, args[0]);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
5511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005513 struct cfg_kw_list *kwl;
5514 int index;
5515
5516 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5517 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5518 if (kwl->kw[index].section != CFG_LISTEN)
5519 continue;
5520 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5521 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005522 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005523 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005524 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005527 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005528 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005529 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005530 err_code |= ERR_WARN;
5531 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005532 }
Willy Tarreau93893792009-07-23 13:19:11 +02005533 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005534 }
5535 }
5536 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005537
Willy Tarreau6daf3432008-01-22 16:44:08 +01005538 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 }
Willy Tarreau93893792009-07-23 13:19:11 +02005542 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005543 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005544 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545}
5546
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005547int
5548cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5549{
5550
5551 int err_code = 0;
5552 const char *err;
5553
5554 if (!strcmp(args[0], "userlist")) { /* new userlist */
5555 struct userlist *newul;
5556
5557 if (!*args[1]) {
5558 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5559 file, linenum, args[0]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563
5564 err = invalid_char(args[1]);
5565 if (err) {
5566 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5567 file, linenum, *err, args[0], args[1]);
5568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
5570 }
5571
5572 for (newul = userlist; newul; newul = newul->next)
5573 if (!strcmp(newul->name, args[1])) {
5574 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5575 file, linenum, args[1]);
5576 err_code |= ERR_WARN;
5577 goto out;
5578 }
5579
5580 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5581 if (!newul) {
5582 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5583 err_code |= ERR_ALERT | ERR_ABORT;
5584 goto out;
5585 }
5586
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005587 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005588 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005589 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5590 err_code |= ERR_ALERT | ERR_ABORT;
5591 goto out;
5592 }
5593
5594 newul->next = userlist;
5595 userlist = newul;
5596
5597 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005598 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005599 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005600 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005601
5602 if (!*args[1]) {
5603 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5604 file, linenum, args[0]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
5608
5609 err = invalid_char(args[1]);
5610 if (err) {
5611 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5612 file, linenum, *err, args[0], args[1]);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005617 for (ag = userlist->groups; ag; ag = ag->next)
5618 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005619 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5620 file, linenum, args[1], userlist->name);
5621 err_code |= ERR_ALERT;
5622 goto out;
5623 }
5624
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005625 ag = calloc(1, sizeof(*ag));
5626 if (!ag) {
5627 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5628 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005629 goto out;
5630 }
5631
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005632 ag->name = strdup(args[1]);
5633 if (!ag) {
5634 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5635 err_code |= ERR_ALERT | ERR_ABORT;
5636 goto out;
5637 }
5638
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005639 cur_arg = 2;
5640
5641 while (*args[cur_arg]) {
5642 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005643 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005644 cur_arg += 2;
5645 continue;
5646 } else {
5647 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5648 file, linenum, args[0]);
5649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
5651 }
5652 }
5653
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005654 ag->next = userlist->groups;
5655 userlist->groups = ag;
5656
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005657 } else if (!strcmp(args[0], "user")) { /* new user */
5658 struct auth_users *newuser;
5659 int cur_arg;
5660
5661 if (!*args[1]) {
5662 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5663 file, linenum, args[0]);
5664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
5666 }
5667
5668 for (newuser = userlist->users; newuser; newuser = newuser->next)
5669 if (!strcmp(newuser->user, args[1])) {
5670 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5671 file, linenum, args[1], userlist->name);
5672 err_code |= ERR_ALERT;
5673 goto out;
5674 }
5675
5676 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5677 if (!newuser) {
5678 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5679 err_code |= ERR_ALERT | ERR_ABORT;
5680 goto out;
5681 }
5682
5683 newuser->user = strdup(args[1]);
5684
5685 newuser->next = userlist->users;
5686 userlist->users = newuser;
5687
5688 cur_arg = 2;
5689
5690 while (*args[cur_arg]) {
5691 if (!strcmp(args[cur_arg], "password")) {
5692#ifndef CONFIG_HAP_CRYPT
5693 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5694 file, linenum);
5695 err_code |= ERR_ALERT;
5696#endif
5697 newuser->pass = strdup(args[cur_arg + 1]);
5698 cur_arg += 2;
5699 continue;
5700 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5701 newuser->pass = strdup(args[cur_arg + 1]);
5702 newuser->flags |= AU_O_INSECURE;
5703 cur_arg += 2;
5704 continue;
5705 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005706 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005707 cur_arg += 2;
5708 continue;
5709 } else {
5710 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5711 file, linenum, args[0]);
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715 }
5716 } else {
5717 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5718 err_code |= ERR_ALERT | ERR_FATAL;
5719 }
5720
5721out:
5722 return err_code;
5723}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724
5725/*
5726 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005727 * Returns the error code, 0 if OK, or any combination of :
5728 * - ERR_ABORT: must abort ASAP
5729 * - ERR_FATAL: we can continue parsing but not start the service
5730 * - ERR_WARN: a warning has been emitted
5731 * - ERR_ALERT: an alert has been emitted
5732 * Only the two first ones can stop processing, the two others are just
5733 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005735int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005737 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 FILE *f;
5739 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005740 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005741 struct cfg_section *cs = NULL;
5742 struct cfg_section *ics;
5743
5744 /* Register internal sections */
5745 if (!cfg_register_section("listen", cfg_parse_listen) ||
5746 !cfg_register_section("frontend", cfg_parse_listen) ||
5747 !cfg_register_section("backend", cfg_parse_listen) ||
5748 !cfg_register_section("ruleset", cfg_parse_listen) ||
5749 !cfg_register_section("defaults", cfg_parse_listen) ||
5750 !cfg_register_section("global", cfg_parse_global) ||
5751 !cfg_register_section("userlist", cfg_parse_users) ||
5752 !cfg_register_section("peers", cfg_parse_peers))
5753 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 if ((f=fopen(file,"r")) == NULL)
5756 return -1;
5757
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005758 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005759 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005760 char *end;
5761 char *args[MAX_LINE_ARGS + 1];
5762 char *line = thisline;
5763
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 linenum++;
5765
5766 end = line + strlen(line);
5767
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005768 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5769 /* Check if we reached the limit and the last char is not \n.
5770 * Watch out for the last line without the terminating '\n'!
5771 */
5772 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005773 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005774 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005775 }
5776
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005778 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 line++;
5780
5781 arg = 0;
5782 args[arg] = line;
5783
5784 while (*line && arg < MAX_LINE_ARGS) {
5785 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5786 * C equivalent value. Other combinations left unchanged (eg: \1).
5787 */
5788 if (*line == '\\') {
5789 int skip = 0;
5790 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5791 *line = line[1];
5792 skip = 1;
5793 }
5794 else if (line[1] == 'r') {
5795 *line = '\r';
5796 skip = 1;
5797 }
5798 else if (line[1] == 'n') {
5799 *line = '\n';
5800 skip = 1;
5801 }
5802 else if (line[1] == 't') {
5803 *line = '\t';
5804 skip = 1;
5805 }
5806 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005807 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 unsigned char hex1, hex2;
5809 hex1 = toupper(line[2]) - '0';
5810 hex2 = toupper(line[3]) - '0';
5811 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5812 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5813 *line = (hex1<<4) + hex2;
5814 skip = 3;
5815 }
5816 else {
5817 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005818 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
5820 }
5821 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005822 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 end -= skip;
5824 }
5825 line++;
5826 }
5827 else if (*line == '#' || *line == '\n' || *line == '\r') {
5828 /* end of string, end of loop */
5829 *line = 0;
5830 break;
5831 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005832 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005834 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005835 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 line++;
5837 args[++arg] = line;
5838 }
5839 else {
5840 line++;
5841 }
5842 }
5843
5844 /* empty line */
5845 if (!**args)
5846 continue;
5847
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005848 if (*line) {
5849 /* we had to stop due to too many args.
5850 * Let's terminate the string, print the offending part then cut the
5851 * last arg.
5852 */
5853 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5854 line++;
5855 *line = '\0';
5856
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005857 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005858 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005859 err_code |= ERR_ALERT | ERR_FATAL;
5860 args[arg] = line;
5861 }
5862
Willy Tarreau540abe42007-05-02 20:50:16 +02005863 /* zero out remaining args and ensure that at least one entry
5864 * is zeroed out.
5865 */
5866 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 args[arg] = line;
5868 }
5869
Willy Tarreau3842f002009-06-14 11:39:52 +02005870 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005871 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005872 char *tmp;
5873
Willy Tarreau3842f002009-06-14 11:39:52 +02005874 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005875 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005876 for (arg=0; *args[arg+1]; arg++)
5877 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005878 *tmp = '\0'; // fix the next arg to \0
5879 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005880 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005881 else if (!strcmp(args[0], "default")) {
5882 kwm = KWM_DEF;
5883 for (arg=0; *args[arg+1]; arg++)
5884 args[arg] = args[arg+1]; // shift args after inversion
5885 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005886
William Lallemand0f99e342011-10-12 17:50:54 +02005887 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5888 strcmp(args[0], "log") != 0) {
5889 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005890 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005891 }
5892
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005893 /* detect section start */
5894 list_for_each_entry(ics, &sections, list) {
5895 if (strcmp(args[0], ics->section_name) == 0) {
5896 cursection = ics->section_name;
5897 cs = ics;
5898 break;
5899 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005900 }
5901
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005903 if (cs)
5904 err_code |= cs->section_parser(file, linenum, args, kwm);
5905 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005906 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005907 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005909
5910 if (err_code & ERR_ABORT)
5911 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005913 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005915 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005916}
5917
Willy Tarreaubb925012009-07-23 13:36:36 +02005918/*
5919 * Returns the error code, 0 if OK, or any combination of :
5920 * - ERR_ABORT: must abort ASAP
5921 * - ERR_FATAL: we can continue parsing but not start the service
5922 * - ERR_WARN: a warning has been emitted
5923 * - ERR_ALERT: an alert has been emitted
5924 * Only the two first ones can stop processing, the two others are just
5925 * indicators.
5926 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005927int check_config_validity()
5928{
5929 int cfgerr = 0;
5930 struct proxy *curproxy = NULL;
5931 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005932 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005933 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005934 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005935
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005936 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 /*
5938 * Now, check for the integrity of all that we have collected.
5939 */
5940
5941 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005942 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943
Willy Tarreau193b8c62012-11-22 00:17:38 +01005944 if (!global.tune.max_http_hdr)
5945 global.tune.max_http_hdr = MAX_HTTP_HDR;
5946
5947 if (!global.tune.cookie_len)
5948 global.tune.cookie_len = CAPTURE_LEN;
5949
5950 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5951
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005952 /* Post initialisation of the users and groups lists. */
5953 err_code = userlist_postinit();
5954 if (err_code != ERR_NONE)
5955 goto out;
5956
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005957 /* first, we will invert the proxy list order */
5958 curproxy = NULL;
5959 while (proxy) {
5960 struct proxy *next;
5961
5962 next = proxy->next;
5963 proxy->next = curproxy;
5964 curproxy = proxy;
5965 if (!next)
5966 break;
5967 proxy = next;
5968 }
5969
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005971 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005972 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005973 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005974 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005975 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005976 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005977 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005978
Willy Tarreau050536d2012-10-04 08:47:34 +02005979 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005980 /* proxy ID not set, use automatic numbering with first
5981 * spare entry starting with next_pxid.
5982 */
5983 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5984 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5985 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005986 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005987 next_pxid++;
5988
Willy Tarreau55ea7572007-06-17 19:56:27 +02005989
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005991 /* ensure we don't keep listeners uselessly bound */
5992 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005993 curproxy = curproxy->next;
5994 continue;
5995 }
5996
Willy Tarreau102df612014-05-07 23:56:38 +02005997 /* Check multi-process mode compatibility for the current proxy */
5998
5999 if (curproxy->bind_proc) {
6000 /* an explicit bind-process was specified, let's check how many
6001 * processes remain.
6002 */
6003 nbproc = popcount(curproxy->bind_proc);
6004
6005 curproxy->bind_proc &= nbits(global.nbproc);
6006 if (!curproxy->bind_proc && nbproc == 1) {
6007 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);
6008 curproxy->bind_proc = 1;
6009 }
6010 else if (!curproxy->bind_proc && nbproc > 1) {
6011 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);
6012 curproxy->bind_proc = 0;
6013 }
6014 }
6015
Willy Tarreau3d209582014-05-09 17:06:11 +02006016 /* check and reduce the bind-proc of each listener */
6017 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6018 unsigned long mask;
6019
6020 if (!bind_conf->bind_proc)
6021 continue;
6022
6023 mask = nbits(global.nbproc);
6024 if (curproxy->bind_proc)
6025 mask &= curproxy->bind_proc;
6026 /* mask cannot be null here thanks to the previous checks */
6027
6028 nbproc = popcount(bind_conf->bind_proc);
6029 bind_conf->bind_proc &= mask;
6030
6031 if (!bind_conf->bind_proc && nbproc == 1) {
6032 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",
6033 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6034 bind_conf->bind_proc = mask & ~(mask - 1);
6035 }
6036 else if (!bind_conf->bind_proc && nbproc > 1) {
6037 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",
6038 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6039 bind_conf->bind_proc = 0;
6040 }
6041 }
6042
Willy Tarreau102df612014-05-07 23:56:38 +02006043 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
6044 * We now check how many processes the proxy will effectively run on.
6045 */
6046
6047 nbproc = global.nbproc;
6048 if (curproxy->bind_proc)
6049 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6050
6051 if (global.nbproc > 1 && curproxy->table.peers.name) {
6052 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6053 curproxy->id);
6054 cfgerr++;
6055 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006056
Willy Tarreauff01a212009-03-15 13:46:16 +01006057 switch (curproxy->mode) {
6058 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006059 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006060 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006061 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6062 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006063 cfgerr++;
6064 }
6065
6066 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006067 Warning("config : servers will be ignored for %s '%s'.\n",
6068 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006069 break;
6070
6071 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006072 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006073 break;
6074
6075 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006076 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006077 break;
6078 }
6079
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006080 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006081 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006082 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006083 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6084 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006085 cfgerr++;
6086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006088 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006089 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6090 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006091 cfgerr++;
6092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006094 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006095 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6096 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006097 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006098 }
6099 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006100 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006101 /* If no LB algo is set in a backend, and we're not in
6102 * transparent mode, dispatch mode nor proxy mode, we
6103 * want to use balance roundrobin by default.
6104 */
6105 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6106 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 }
6108 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006109
Willy Tarreau1620ec32011-08-06 17:05:02 +02006110 if (curproxy->options & PR_O_DISPATCH)
6111 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6112 else if (curproxy->options & PR_O_HTTP_PROXY)
6113 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6114 else if (curproxy->options & PR_O_TRANSP)
6115 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006116
Willy Tarreau1620ec32011-08-06 17:05:02 +02006117 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6118 if (curproxy->options & PR_O_DISABLE404) {
6119 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6120 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6121 err_code |= ERR_WARN;
6122 curproxy->options &= ~PR_O_DISABLE404;
6123 }
6124 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6125 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6126 "send-state", proxy_type_str(curproxy), curproxy->id);
6127 err_code |= ERR_WARN;
6128 curproxy->options &= ~PR_O2_CHK_SNDST;
6129 }
Willy Tarreauef781042010-01-27 11:53:01 +01006130 }
6131
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006132 /* if a default backend was specified, let's find it */
6133 if (curproxy->defbe.name) {
6134 struct proxy *target;
6135
Alex Williams96532db2009-11-01 21:27:13 -05006136 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006137 if (!target) {
6138 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6139 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006140 cfgerr++;
6141 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006142 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6143 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006144 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006145 } else {
6146 free(curproxy->defbe.name);
6147 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006148 /* we force the backend to be present on at least all of
6149 * the frontend's processes.
6150 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006151 if (target->bind_proc)
6152 target->bind_proc = curproxy->bind_proc ?
6153 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006154
6155 /* Emit a warning if this proxy also has some servers */
6156 if (curproxy->srv) {
6157 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6158 curproxy->id);
6159 err_code |= ERR_WARN;
6160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 }
6162 }
6163
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006164 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006165 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6166 /* map jump target for ACT_SETBE in req_rep chain */
6167 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006168 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006169 struct proxy *target;
6170
Willy Tarreaua496b602006-12-17 23:15:24 +01006171 if (exp->action != ACT_SETBE)
6172 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006173
Alex Williams96532db2009-11-01 21:27:13 -05006174 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006175 if (!target) {
6176 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6177 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006178 cfgerr++;
6179 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006180 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6181 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006182 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006183 } else {
6184 free((void *)exp->replace);
6185 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006186 /* we force the backend to be present on at least all of
6187 * the frontend's processes.
6188 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006189 if (target->bind_proc)
6190 target->bind_proc = curproxy->bind_proc ?
6191 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006192 }
6193 }
6194 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006195
6196 /* find the target proxy for 'use_backend' rules */
6197 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006198 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006199 struct logformat_node *node;
6200 char *pxname;
6201
6202 /* Try to parse the string as a log format expression. If the result
6203 * of the parsing is only one entry containing a simple string, then
6204 * it's a standard string corresponding to a static rule, thus the
6205 * parsing is cancelled and be.name is restored to be resolved.
6206 */
6207 pxname = rule->be.name;
6208 LIST_INIT(&rule->be.expr);
6209 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6210 curproxy->conf.args.file, curproxy->conf.args.line);
6211 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6212
6213 if (!LIST_ISEMPTY(&rule->be.expr)) {
6214 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6215 rule->dynamic = 1;
6216 free(pxname);
6217 continue;
6218 }
6219 /* simple string: free the expression and fall back to static rule */
6220 free(node->arg);
6221 free(node);
6222 }
6223
6224 rule->dynamic = 0;
6225 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006226
Alex Williams96532db2009-11-01 21:27:13 -05006227 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006228
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006229 if (!target) {
6230 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6231 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006232 cfgerr++;
6233 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006234 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6235 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006236 cfgerr++;
6237 } else {
6238 free((void *)rule->be.name);
6239 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006240 /* we force the backend to be present on at least all of
6241 * the frontend's processes.
6242 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006243 if (target->bind_proc)
6244 target->bind_proc = curproxy->bind_proc ?
6245 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006246 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006247 }
6248
6249 /* find the target proxy for 'use_backend' rules */
6250 list_for_each_entry(srule, &curproxy->server_rules, list) {
6251 struct server *target = findserver(curproxy, srule->srv.name);
6252
6253 if (!target) {
6254 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6255 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6256 cfgerr++;
6257 continue;
6258 }
6259 free((void *)srule->srv.name);
6260 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006261 }
6262
Emeric Brunb982a3d2010-01-04 15:45:53 +01006263 /* find the target table for 'stick' rules */
6264 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6265 struct proxy *target;
6266
Emeric Brun1d33b292010-01-04 15:47:17 +01006267 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6268 if (mrule->flags & STK_IS_STORE)
6269 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6270
Emeric Brunb982a3d2010-01-04 15:45:53 +01006271 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006272 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006273 else
6274 target = curproxy;
6275
6276 if (!target) {
6277 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6278 curproxy->id, mrule->table.name);
6279 cfgerr++;
6280 }
6281 else if (target->table.size == 0) {
6282 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6283 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6284 cfgerr++;
6285 }
Willy Tarreau12785782012-04-27 21:37:17 +02006286 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6287 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006288 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6289 cfgerr++;
6290 }
6291 else {
6292 free((void *)mrule->table.name);
6293 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006294 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006295 }
6296 }
6297
6298 /* find the target table for 'store response' rules */
6299 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6300 struct proxy *target;
6301
Emeric Brun1d33b292010-01-04 15:47:17 +01006302 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6303
Emeric Brunb982a3d2010-01-04 15:45:53 +01006304 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006305 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006306 else
6307 target = curproxy;
6308
6309 if (!target) {
6310 Alert("Proxy '%s': unable to find store table '%s'.\n",
6311 curproxy->id, mrule->table.name);
6312 cfgerr++;
6313 }
6314 else if (target->table.size == 0) {
6315 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6316 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6317 cfgerr++;
6318 }
Willy Tarreau12785782012-04-27 21:37:17 +02006319 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6320 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006321 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6322 cfgerr++;
6323 }
6324 else {
6325 free((void *)mrule->table.name);
6326 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006327 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006328 }
6329 }
6330
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006331 /* find the target table for 'tcp-request' layer 4 rules */
6332 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6333 struct proxy *target;
6334
Willy Tarreaub4c84932013-07-23 19:15:30 +02006335 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006336 continue;
6337
6338 if (trule->act_prm.trk_ctr.table.n)
6339 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6340 else
6341 target = curproxy;
6342
6343 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006344 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6345 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006346 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006347 cfgerr++;
6348 }
6349 else if (target->table.size == 0) {
6350 Alert("Proxy '%s': table '%s' used but not configured.\n",
6351 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6352 cfgerr++;
6353 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006354 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6355 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6356 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 +01006357 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006358 cfgerr++;
6359 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006360 else {
6361 free(trule->act_prm.trk_ctr.table.n);
6362 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006363 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006364 * to pass a list of counters to track and allocate them right here using
6365 * stktable_alloc_data_type().
6366 */
6367 }
6368 }
6369
Willy Tarreaud1f96522010-08-03 19:34:32 +02006370 /* find the target table for 'tcp-request' layer 6 rules */
6371 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6372 struct proxy *target;
6373
Willy Tarreaub4c84932013-07-23 19:15:30 +02006374 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006375 continue;
6376
6377 if (trule->act_prm.trk_ctr.table.n)
6378 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6379 else
6380 target = curproxy;
6381
6382 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006383 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6384 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006385 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006386 cfgerr++;
6387 }
6388 else if (target->table.size == 0) {
6389 Alert("Proxy '%s': table '%s' used but not configured.\n",
6390 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6391 cfgerr++;
6392 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006393 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6394 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6395 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 +01006396 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006397 cfgerr++;
6398 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006399 else {
6400 free(trule->act_prm.trk_ctr.table.n);
6401 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006402 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006403 * to pass a list of counters to track and allocate them right here using
6404 * stktable_alloc_data_type().
6405 */
6406 }
6407 }
6408
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006409 /* move any "block" rules at the beginning of the http-request rules */
6410 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6411 /* insert block_rules into http_req_rules at the beginning */
6412 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6413 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6414 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6415 curproxy->http_req_rules.n = curproxy->block_rules.n;
6416 LIST_INIT(&curproxy->block_rules);
6417 }
6418
Emeric Brun32da3c42010-09-23 18:39:19 +02006419 if (curproxy->table.peers.name) {
6420 struct peers *curpeers = peers;
6421
6422 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6423 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6424 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006425 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006426 break;
6427 }
6428 }
6429
6430 if (!curpeers) {
6431 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6432 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006433 free((void *)curproxy->table.peers.name);
6434 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006435 cfgerr++;
6436 }
6437 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006438 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6439 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006440 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006441 cfgerr++;
6442 }
6443 }
6444
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006445 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006446 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006447 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6448 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6449 "proxy", curproxy->id);
6450 cfgerr++;
6451 goto out_uri_auth_compat;
6452 }
6453
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006454 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006455 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006456 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006457 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006458
Willy Tarreau95fa4692010-02-01 13:05:50 +01006459 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6460 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006461
6462 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006463 uri_auth_compat_req[i++] = "realm";
6464 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6465 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006466
Willy Tarreau95fa4692010-02-01 13:05:50 +01006467 uri_auth_compat_req[i++] = "unless";
6468 uri_auth_compat_req[i++] = "{";
6469 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6470 uri_auth_compat_req[i++] = "}";
6471 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006472
Willy Tarreauff011f22011-01-06 17:51:27 +01006473 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6474 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006475 cfgerr++;
6476 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006477 }
6478
Willy Tarreauff011f22011-01-06 17:51:27 +01006479 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006480
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006481 if (curproxy->uri_auth->auth_realm) {
6482 free(curproxy->uri_auth->auth_realm);
6483 curproxy->uri_auth->auth_realm = NULL;
6484 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006485
6486 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006487 }
6488out_uri_auth_compat:
6489
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006490 /* compile the log format */
6491 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006492 if (curproxy->conf.logformat_string != default_http_log_format &&
6493 curproxy->conf.logformat_string != default_tcp_log_format &&
6494 curproxy->conf.logformat_string != clf_http_log_format)
6495 free(curproxy->conf.logformat_string);
6496 curproxy->conf.logformat_string = NULL;
6497 free(curproxy->conf.lfs_file);
6498 curproxy->conf.lfs_file = NULL;
6499 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006500 }
6501
Willy Tarreau62a61232013-04-12 18:13:46 +02006502 if (curproxy->conf.logformat_string) {
6503 curproxy->conf.args.ctx = ARGC_LOG;
6504 curproxy->conf.args.file = curproxy->conf.lfs_file;
6505 curproxy->conf.args.line = curproxy->conf.lfs_line;
6506 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006507 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006508 curproxy->conf.args.file = NULL;
6509 curproxy->conf.args.line = 0;
6510 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006511
Willy Tarreau62a61232013-04-12 18:13:46 +02006512 if (curproxy->conf.uniqueid_format_string) {
6513 curproxy->conf.args.ctx = ARGC_UIF;
6514 curproxy->conf.args.file = curproxy->conf.uif_file;
6515 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006516 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006517 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6518 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006519 curproxy->conf.args.file = NULL;
6520 curproxy->conf.args.line = 0;
6521 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006522
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006523 /* only now we can check if some args remain unresolved.
6524 * This must be done after the users and groups resolution.
6525 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006526 cfgerr += smp_resolve_args(curproxy);
6527 if (!cfgerr)
6528 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006529
Willy Tarreau2738a142006-07-08 17:28:09 +02006530 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006531 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006532 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006533 (!curproxy->timeout.connect ||
6534 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006535 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006536 " | While not properly invalid, you will certainly encounter various problems\n"
6537 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006538 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006539 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006540 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006541 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006542
Willy Tarreau1fa31262007-12-03 00:36:16 +01006543 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6544 * We must still support older configurations, so let's find out whether those
6545 * parameters have been set or must be copied from contimeouts.
6546 */
6547 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006548 if (!curproxy->timeout.tarpit ||
6549 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006550 /* tarpit timeout not set. We search in the following order:
6551 * default.tarpit, curr.connect, default.connect.
6552 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006553 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006554 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006555 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006556 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006557 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006558 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006559 }
6560 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006561 (!curproxy->timeout.queue ||
6562 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006563 /* queue timeout not set. We search in the following order:
6564 * default.queue, curr.connect, default.connect.
6565 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006566 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006567 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006568 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006569 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006570 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006571 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006572 }
6573 }
6574
Willy Tarreau1620ec32011-08-06 17:05:02 +02006575 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006576 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6577 curproxy->check_req = (char *)malloc(curproxy->check_len);
6578 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006579 }
6580
Willy Tarreau215663d2014-06-13 18:30:23 +02006581 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6582 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6583 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6584 proxy_type_str(curproxy), curproxy->id);
6585 err_code |= ERR_WARN;
6586 }
6587
Willy Tarreau193b8c62012-11-22 00:17:38 +01006588 /* ensure that cookie capture length is not too large */
6589 if (curproxy->capture_len >= global.tune.cookie_len) {
6590 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6591 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6592 err_code |= ERR_WARN;
6593 curproxy->capture_len = global.tune.cookie_len - 1;
6594 }
6595
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006596 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006597 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006598 curproxy->req_cap_pool = create_pool("ptrcap",
6599 curproxy->nb_req_cap * sizeof(char *),
6600 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006601 }
6602
6603 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006604 curproxy->rsp_cap_pool = create_pool("ptrcap",
6605 curproxy->nb_rsp_cap * sizeof(char *),
6606 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006607 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006608
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 /* first, we will invert the servers list order */
6610 newsrv = NULL;
6611 while (curproxy->srv) {
6612 struct server *next;
6613
6614 next = curproxy->srv->next;
6615 curproxy->srv->next = newsrv;
6616 newsrv = curproxy->srv;
6617 if (!next)
6618 break;
6619 curproxy->srv = next;
6620 }
6621
Willy Tarreau17edc812014-01-03 12:14:34 +01006622 /* Check that no server name conflicts. This causes trouble in the stats.
6623 * We only emit a warning for the first conflict affecting each server,
6624 * in order to avoid combinatory explosion if all servers have the same
6625 * name. We do that only for servers which do not have an explicit ID,
6626 * because these IDs were made also for distinguishing them and we don't
6627 * want to annoy people who correctly manage them.
6628 */
6629 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6630 struct server *other_srv;
6631
6632 if (newsrv->puid)
6633 continue;
6634
6635 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6636 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6637 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6638 newsrv->conf.file, newsrv->conf.line,
6639 proxy_type_str(curproxy), curproxy->id,
6640 newsrv->id, other_srv->conf.line);
6641 break;
6642 }
6643 }
6644 }
6645
Willy Tarreaudd701652010-05-25 23:03:02 +02006646 /* assign automatic UIDs to servers which don't have one yet */
6647 next_id = 1;
6648 newsrv = curproxy->srv;
6649 while (newsrv != NULL) {
6650 if (!newsrv->puid) {
6651 /* server ID not set, use automatic numbering with first
6652 * spare entry starting with next_svid.
6653 */
6654 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6655 newsrv->conf.id.key = newsrv->puid = next_id;
6656 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6657 }
6658 next_id++;
6659 newsrv = newsrv->next;
6660 }
6661
Willy Tarreau20697042007-11-15 23:26:18 +01006662 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006663 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006664
Willy Tarreau62c3be22012-01-20 13:12:32 +01006665 /*
6666 * If this server supports a maxconn parameter, it needs a dedicated
6667 * tasks to fill the emptied slots when a connection leaves.
6668 * Also, resolve deferred tracking dependency if needed.
6669 */
6670 newsrv = curproxy->srv;
6671 while (newsrv != NULL) {
6672 if (newsrv->minconn > newsrv->maxconn) {
6673 /* Only 'minconn' was specified, or it was higher than or equal
6674 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6675 * this will avoid further useless expensive computations.
6676 */
6677 newsrv->maxconn = newsrv->minconn;
6678 } else if (newsrv->maxconn && !newsrv->minconn) {
6679 /* minconn was not specified, so we set it to maxconn */
6680 newsrv->minconn = newsrv->maxconn;
6681 }
6682
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006683#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006684 if (newsrv->use_ssl || newsrv->check.use_ssl)
6685 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006686#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006687
Willy Tarreau2f075e92013-12-03 11:11:34 +01006688 /* set the check type on the server */
6689 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6690
Willy Tarreau62c3be22012-01-20 13:12:32 +01006691 if (newsrv->trackit) {
6692 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006693 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006694 char *pname, *sname;
6695
6696 pname = newsrv->trackit;
6697 sname = strrchr(pname, '/');
6698
6699 if (sname)
6700 *sname++ = '\0';
6701 else {
6702 sname = pname;
6703 pname = NULL;
6704 }
6705
6706 if (pname) {
6707 px = findproxy(pname, PR_CAP_BE);
6708 if (!px) {
6709 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6710 proxy_type_str(curproxy), curproxy->id,
6711 newsrv->id, pname);
6712 cfgerr++;
6713 goto next_srv;
6714 }
6715 } else
6716 px = curproxy;
6717
6718 srv = findserver(px, sname);
6719 if (!srv) {
6720 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6721 proxy_type_str(curproxy), curproxy->id,
6722 newsrv->id, sname);
6723 cfgerr++;
6724 goto next_srv;
6725 }
6726
Willy Tarreau32091232014-05-16 13:52:00 +02006727 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6728 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6729 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006730 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006731 "tracking as it does not have any check nor agent enabled.\n",
6732 proxy_type_str(curproxy), curproxy->id,
6733 newsrv->id, px->id, srv->id);
6734 cfgerr++;
6735 goto next_srv;
6736 }
6737
6738 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6739
6740 if (loop) {
6741 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6742 "belongs to a tracking chain looping back to %s/%s.\n",
6743 proxy_type_str(curproxy), curproxy->id,
6744 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006745 cfgerr++;
6746 goto next_srv;
6747 }
6748
6749 if (curproxy != px &&
6750 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6751 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6752 "tracking: disable-on-404 option inconsistency.\n",
6753 proxy_type_str(curproxy), curproxy->id,
6754 newsrv->id, px->id, srv->id);
6755 cfgerr++;
6756 goto next_srv;
6757 }
6758
6759 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006760 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006761 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006762 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006763 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006764 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006765 }
6766
6767 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006768 newsrv->tracknext = srv->trackers;
6769 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006770
6771 free(newsrv->trackit);
6772 newsrv->trackit = NULL;
6773 }
6774 next_srv:
6775 newsrv = newsrv->next;
6776 }
6777
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006778 /* We have to initialize the server lookup mechanism depending
6779 * on what LB algorithm was choosen.
6780 */
6781
6782 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6783 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6784 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006785 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6786 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6787 init_server_map(curproxy);
6788 } else {
6789 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6790 fwrr_init_server_groups(curproxy);
6791 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006792 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006793
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006794 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006795 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6796 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6797 fwlc_init_server_tree(curproxy);
6798 } else {
6799 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6800 fas_init_server_tree(curproxy);
6801 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006802 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006803
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006804 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006805 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6806 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6807 chash_init_server_tree(curproxy);
6808 } else {
6809 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6810 init_server_map(curproxy);
6811 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006812 break;
6813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006814
6815 if (curproxy->options & PR_O_LOGASAP)
6816 curproxy->to_log &= ~LW_BYTES;
6817
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006818 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006819 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006820 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6821 proxy_type_str(curproxy), curproxy->id);
6822 err_code |= ERR_WARN;
6823 }
6824
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006825 if (curproxy->mode != PR_MODE_HTTP) {
6826 int optnum;
6827
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006828 if (curproxy->uri_auth) {
6829 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6830 proxy_type_str(curproxy), curproxy->id);
6831 err_code |= ERR_WARN;
6832 curproxy->uri_auth = NULL;
6833 }
6834
Willy Tarreau87cf5142011-08-19 22:57:24 +02006835 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006836 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6837 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6838 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006839 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006840 }
6841
6842 if (curproxy->options & PR_O_ORGTO) {
6843 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6844 "originalto", proxy_type_str(curproxy), curproxy->id);
6845 err_code |= ERR_WARN;
6846 curproxy->options &= ~PR_O_ORGTO;
6847 }
6848
6849 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6850 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6851 (curproxy->cap & cfg_opts[optnum].cap) &&
6852 (curproxy->options & cfg_opts[optnum].val)) {
6853 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6854 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6855 err_code |= ERR_WARN;
6856 curproxy->options &= ~cfg_opts[optnum].val;
6857 }
6858 }
6859
6860 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6861 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6862 (curproxy->cap & cfg_opts2[optnum].cap) &&
6863 (curproxy->options2 & cfg_opts2[optnum].val)) {
6864 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6865 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6866 err_code |= ERR_WARN;
6867 curproxy->options2 &= ~cfg_opts2[optnum].val;
6868 }
6869 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006870
Pieter Baauwd551fb52013-05-08 22:49:23 +02006871#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006872 if (curproxy->conn_src.bind_hdr_occ) {
6873 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006874 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006875 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006876 err_code |= ERR_WARN;
6877 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006878#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006879 }
6880
Willy Tarreaubaaee002006-06-26 02:48:02 +02006881 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006882 * ensure that we're not cross-dressing a TCP server into HTTP.
6883 */
6884 newsrv = curproxy->srv;
6885 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006886 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006887 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6888 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006889 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006890 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006891
Willy Tarreau0cec3312011-10-31 13:49:26 +01006892 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6893 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6894 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6895 err_code |= ERR_WARN;
6896 }
6897
Willy Tarreauc93cd162014-05-13 15:54:22 +02006898 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006899 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6900 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6901 err_code |= ERR_WARN;
6902 }
6903
Pieter Baauwd551fb52013-05-08 22:49:23 +02006904#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006905 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6906 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006907 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 +01006908 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006909 err_code |= ERR_WARN;
6910 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006911#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006912 newsrv = newsrv->next;
6913 }
6914
Willy Tarreauc1a21672009-08-16 22:37:44 +02006915 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006916 if (!curproxy->accept)
6917 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006918
Willy Tarreauc1a21672009-08-16 22:37:44 +02006919 if (curproxy->tcp_req.inspect_delay ||
6920 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006921 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006922
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006923 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006924 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006925 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006926 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006927
6928 /* both TCP and HTTP must check switching rules */
6929 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6930 }
6931
6932 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006933 if (curproxy->tcp_req.inspect_delay ||
6934 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6935 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6936
Emeric Brun97679e72010-09-23 17:56:44 +02006937 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6938 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6939
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006940 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006941 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006942 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006943 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006944
6945 /* If the backend does requires RDP cookie persistence, we have to
6946 * enable the corresponding analyser.
6947 */
6948 if (curproxy->options2 & PR_O2_RDPC_PRST)
6949 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6950 }
6951
Emeric Brunc52962f2012-11-15 18:28:02 +01006952#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006953 /* Configure SSL for each bind line.
6954 * Note: if configuration fails at some point, the ->ctx member
6955 * remains NULL so that listeners can later detach.
6956 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006957 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006958 int alloc_ctx;
6959
Emeric Brunc52962f2012-11-15 18:28:02 +01006960 if (!bind_conf->is_ssl) {
6961 if (bind_conf->default_ctx) {
6962 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6963 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6964 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006965 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006966 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006967 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006968 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006969 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006970 cfgerr++;
6971 continue;
6972 }
6973
Emeric Brun8dc60392014-05-09 13:52:00 +02006974 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006975 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006976 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6977 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");
6978 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006979 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006980 cfgerr++;
6981 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006982 }
6983
Emeric Brunfc0421f2012-09-07 17:30:07 +02006984 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006985 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006986 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006987#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006988
Willy Tarreaue6b98942007-10-29 01:09:36 +01006989 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006990 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006991 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006992 if (!listener->luid) {
6993 /* listener ID not set, use automatic numbering with first
6994 * spare entry starting with next_luid.
6995 */
6996 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6997 listener->conf.id.key = listener->luid = next_id;
6998 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006999 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007000 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007001
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007002 /* enable separate counters */
7003 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7004 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007005 if (!listener->name)
7006 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007007 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007008
Willy Tarreaue6b98942007-10-29 01:09:36 +01007009 if (curproxy->options & PR_O_TCP_NOLING)
7010 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007011 if (!listener->maxconn)
7012 listener->maxconn = curproxy->maxconn;
7013 if (!listener->backlog)
7014 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007015 if (!listener->maxaccept)
7016 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7017
7018 /* we want to have an optimal behaviour on single process mode to
7019 * maximize the work at once, but in multi-process we want to keep
7020 * some fairness between processes, so we target half of the max
7021 * number of events to be balanced over all the processes the proxy
7022 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7023 * used to disable the limit.
7024 */
7025 if (listener->maxaccept > 0) {
7026 if (nbproc > 1)
7027 listener->maxaccept = (listener->maxaccept + 1) / 2;
7028 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7029 }
7030
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007031 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007032 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007033 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007034 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007035
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007036 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7037 listener->options |= LI_O_TCP_RULES;
7038
Willy Tarreaude3041d2010-05-31 10:56:17 +02007039 if (curproxy->mon_mask.s_addr)
7040 listener->options |= LI_O_CHK_MONNET;
7041
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007042 /* smart accept mode is automatic in HTTP mode */
7043 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007044 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007045 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7046 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007047 }
7048
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007049 /* Release unused SSL configs */
7050 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7051 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007052 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007053#ifdef USE_OPENSSL
7054 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007055 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007056 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007057 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007058 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007059#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007060 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007061
Willy Tarreau102df612014-05-07 23:56:38 +02007062 if (nbproc > 1) {
7063 if (curproxy->uri_auth) {
7064 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7065 curproxy->id);
7066 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7067 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7068 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007069 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007070 }
Willy Tarreau102df612014-05-07 23:56:38 +02007071 if (curproxy->appsession_name) {
7072 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7073 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007074 }
Willy Tarreau102df612014-05-07 23:56:38 +02007075 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7076 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7077 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007078 }
7079 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007080
7081 /* create the task associated with the proxy */
7082 curproxy->task = task_new();
7083 if (curproxy->task) {
7084 curproxy->task->context = curproxy;
7085 curproxy->task->process = manage_proxy;
7086 /* no need to queue, it will be done automatically if some
7087 * listener gets limited.
7088 */
7089 curproxy->task->expire = TICK_ETERNITY;
7090 } else {
7091 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7092 curproxy->id);
7093 cfgerr++;
7094 }
7095
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 curproxy = curproxy->next;
7097 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007098
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007099 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007100 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007101 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7102 unsigned long mask;
7103
7104 mask = nbits(global.nbproc);
7105 if (global.stats_fe->bind_proc)
7106 mask &= global.stats_fe->bind_proc;
7107
7108 if (bind_conf->bind_proc)
7109 mask &= bind_conf->bind_proc;
7110
7111 /* stop here if more than one process is used */
7112 if (popcount(mask) > 1)
7113 break;
7114 }
7115 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7116 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");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007117 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007118 }
7119
7120 /* automatically compute fullconn if not set. We must not do it in the
7121 * loop above because cross-references are not yet fully resolved.
7122 */
7123 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7124 /* If <fullconn> is not set, let's set it to 10% of the sum of
7125 * the possible incoming frontend's maxconns.
7126 */
7127 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7128 struct proxy *fe;
7129 int total = 0;
7130
7131 /* sum up the number of maxconns of frontends which
7132 * reference this backend at least once or which are
7133 * the same one ('listen').
7134 */
7135 for (fe = proxy; fe; fe = fe->next) {
7136 struct switching_rule *rule;
7137 struct hdr_exp *exp;
7138 int found = 0;
7139
7140 if (!(fe->cap & PR_CAP_FE))
7141 continue;
7142
7143 if (fe == curproxy) /* we're on a "listen" instance */
7144 found = 1;
7145
7146 if (fe->defbe.be == curproxy) /* "default_backend" */
7147 found = 1;
7148
7149 /* check if a "use_backend" rule matches */
7150 if (!found) {
7151 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007152 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007153 found = 1;
7154 break;
7155 }
7156 }
7157 }
7158
7159 /* check if a "reqsetbe" rule matches */
7160 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7161 if (exp->action == ACT_SETBE &&
7162 (struct proxy *)exp->replace == curproxy) {
7163 found = 1;
7164 break;
7165 }
7166 }
7167
7168 /* now we've checked all possible ways to reference a backend
7169 * from a frontend.
7170 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007171 if (!found)
7172 continue;
7173 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007174 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007175 /* we have the sum of the maxconns in <total>. We only
7176 * keep 10% of that sum to set the default fullconn, with
7177 * a hard minimum of 1 (to avoid a divide by zero).
7178 */
7179 curproxy->fullconn = (total + 9) / 10;
7180 if (!curproxy->fullconn)
7181 curproxy->fullconn = 1;
7182 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007183 }
7184
Willy Tarreau056f5682010-06-06 15:51:11 +02007185 /* initialize stick-tables on backend capable proxies. This must not
7186 * be done earlier because the data size may be discovered while parsing
7187 * other proxies.
7188 */
Godbach9703e662013-12-11 21:11:41 +08007189 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007190 if (curproxy->state == PR_STSTOPPED)
7191 continue;
7192
Godbach9703e662013-12-11 21:11:41 +08007193 if (!stktable_init(&curproxy->table)) {
7194 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7195 cfgerr++;
7196 }
7197 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007198
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007199 /*
7200 * Recount currently required checks.
7201 */
7202
7203 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7204 int optnum;
7205
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007206 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7207 if (curproxy->options & cfg_opts[optnum].val)
7208 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007209
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007210 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7211 if (curproxy->options2 & cfg_opts2[optnum].val)
7212 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007213 }
7214
Willy Tarreau122541c2011-09-07 21:24:49 +02007215 if (peers) {
7216 struct peers *curpeers = peers, **last;
7217 struct peer *p, *pb;
7218
7219 /* Remove all peers sections which don't have a valid listener.
7220 * This can happen when a peers section is never referenced and
7221 * does not contain a local peer.
7222 */
7223 last = &peers;
7224 while (*last) {
7225 curpeers = *last;
7226 if (curpeers->peers_fe) {
7227 last = &curpeers->next;
7228 continue;
7229 }
7230
7231 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7232 curpeers->id, localpeer);
7233
7234 p = curpeers->remote;
7235 while (p) {
7236 pb = p->next;
7237 free(p->id);
7238 free(p);
7239 p = pb;
7240 }
7241
7242 /* Destroy and unlink this curpeers section.
7243 * Note: curpeers is backed up into *last.
7244 */
7245 free(curpeers->id);
7246 curpeers = curpeers->next;
7247 free(*last);
7248 *last = curpeers;
7249 }
7250 }
7251
Willy Tarreau34eb6712011-10-24 18:15:04 +02007252 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007253 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007254 MEM_F_SHARED);
7255
Willy Tarreaubb925012009-07-23 13:36:36 +02007256 if (cfgerr > 0)
7257 err_code |= ERR_ALERT | ERR_FATAL;
7258 out:
7259 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260}
7261
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007262/*
7263 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7264 * parsing sessions.
7265 */
7266void cfg_register_keywords(struct cfg_kw_list *kwl)
7267{
7268 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7269}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007270
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007271/*
7272 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7273 */
7274void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7275{
7276 LIST_DEL(&kwl->list);
7277 LIST_INIT(&kwl->list);
7278}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007280/* this function register new section in the haproxy configuration file.
7281 * <section_name> is the name of this new section and <section_parser>
7282 * is the called parser. If two section declaration have the same name,
7283 * only the first declared is used.
7284 */
7285int cfg_register_section(char *section_name,
7286 int (*section_parser)(const char *, int, char **, int))
7287{
7288 struct cfg_section *cs;
7289
7290 cs = calloc(1, sizeof(*cs));
7291 if (!cs) {
7292 Alert("register section '%s': out of memory.\n", section_name);
7293 return 0;
7294 }
7295
7296 cs->section_name = section_name;
7297 cs->section_parser = section_parser;
7298
7299 LIST_ADDQ(&sections, &cs->list);
7300
7301 return 1;
7302}
7303
Willy Tarreaubaaee002006-06-26 02:48:02 +02007304/*
7305 * Local variables:
7306 * c-indent-level: 8
7307 * c-basic-offset: 8
7308 * End:
7309 */