blob: decdcfd0e2fca1643021e8361cf2091a2b4ef6fb [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 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200636#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200637 else if (!strcmp(args[0], "tune.bufsize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.bufsize = atol(args[1]);
644 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
645 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100646 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100647 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200648 }
649 else if (!strcmp(args[0], "tune.maxrewrite")) {
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.maxrewrite = atol(args[1]);
656 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
657 global.tune.maxrewrite = global.tune.bufsize / 2;
658 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100659 else if (!strcmp(args[0], "tune.idletimer")) {
660 unsigned int idle;
661 const char *res;
662
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668
669 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
670 if (res) {
671 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
672 file, linenum, *res, args[0]);
673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
675 }
676
677 if (idle > 65535) {
678 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.idle_timer = idle;
683 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100684 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
685 if (global.tune.client_rcvbuf != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT;
688 goto out;
689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.client_rcvbuf = atol(args[1]);
696 }
697 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
698 if (global.tune.server_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.server_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.sndbuf.client")) {
711 if (global.tune.client_sndbuf != 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.client_sndbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.server")) {
724 if (global.tune.server_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.server_sndbuf = atol(args[1]);
735 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200736 else if (!strcmp(args[0], "tune.pipesize")) {
737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.tune.pipesize = atol(args[1]);
743 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100744 else if (!strcmp(args[0], "tune.http.cookielen")) {
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750 global.tune.cookie_len = atol(args[1]) + 1;
751 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200752 else if (!strcmp(args[0], "tune.http.maxhdr")) {
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 global.tune.max_http_hdr = atol(args[1]);
759 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100760 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
761#ifdef USE_ZLIB
762 if (*args[1]) {
763 global.tune.zlibmemlevel = atoi(args[1]);
764 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
765 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
766 file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 } else {
771 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
772 file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
776#else
777 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780#endif
781 }
782 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
783#ifdef USE_ZLIB
784 if (*args[1]) {
785 global.tune.zlibwindowsize = atoi(args[1]);
786 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
787 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
788 file, linenum, args[0]);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
791 }
792 } else {
793 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
794 file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798#else
799 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802#endif
803 }
William Lallemandf3747832012-11-09 12:33:10 +0100804 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
805 if (*args[1]) {
806 global.tune.comp_maxlevel = atoi(args[1]);
807 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
808 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
809 file, linenum, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813 } else {
814 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
815 file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 else if (!strcmp(args[0], "uid")) {
821 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200822 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200823 err_code |= ERR_ALERT;
824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 }
826 if (*(args[1]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 }
831 global.uid = atol(args[1]);
832 }
833 else if (!strcmp(args[0], "gid")) {
834 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : group/gid 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.gid = atol(args[1]);
845 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200846 /* user/group name handling */
847 else if (!strcmp(args[0], "user")) {
848 struct passwd *ha_user;
849 if (global.uid != 0) {
850 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT;
852 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200853 }
854 errno = 0;
855 ha_user = getpwnam(args[1]);
856 if (ha_user != NULL) {
857 global.uid = (int)ha_user->pw_uid;
858 }
859 else {
860 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 +0200861 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200862 }
863 }
864 else if (!strcmp(args[0], "group")) {
865 struct group *ha_group;
866 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200867 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
869 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200870 }
871 errno = 0;
872 ha_group = getgrnam(args[1]);
873 if (ha_group != NULL) {
874 global.gid = (int)ha_group->gr_gid;
875 }
876 else {
877 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 +0200878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200879 }
880 }
881 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100889 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
890 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
891 file, linenum, args[0], LONGBITS, global.nbproc);
892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 }
896 else if (!strcmp(args[0], "maxconn")) {
897 if (global.maxconn != 0) {
898 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 err_code |= ERR_ALERT;
900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 }
902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 }
907 global.maxconn = atol(args[1]);
908#ifdef SYSTEM_MAXCONN
909 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
910 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);
911 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914#endif /* SYSTEM_MAXCONN */
915 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200916 else if (!strcmp(args[0], "maxsslconn")) {
917#ifdef USE_OPENSSL
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 global.maxsslconn = atol(args[1]);
924#else
Emeric Brun0914df82012-10-02 18:45:42 +0200925 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200928#endif
929 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100930 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
931#ifdef USE_OPENSSL
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 free(global.listen_default_ciphers);
938 global.listen_default_ciphers = strdup(args[1]);
939#else
940 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943#endif
944 }
945 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
946#ifdef USE_OPENSSL
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 free(global.connect_default_ciphers);
953 global.connect_default_ciphers = strdup(args[1]);
954#else
955 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958#endif
959 }
Emeric Brun850efd52014-01-29 12:24:34 +0100960 else if (!strcmp(args[0], "ssl-server-verify")) {
961 if (*(args[1]) == 0) {
962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 if (strcmp(args[1],"none") == 0)
967 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
968 else if (strcmp(args[1],"required") == 0)
969 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
970 else {
971 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200976 else if (!strcmp(args[0], "maxconnrate")) {
977 if (global.cps_lim != 0) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT;
980 goto out;
981 }
982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987 global.cps_lim = atol(args[1]);
988 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200989 else if (!strcmp(args[0], "maxsessrate")) {
990 if (global.sps_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.sps_lim = atol(args[1]);
1001 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001002 else if (!strcmp(args[0], "maxsslrate")) {
1003 if (global.ssl_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.ssl_lim = atol(args[1]);
1014 }
William Lallemandd85f9172012-11-09 17:05:39 +01001015 else if (!strcmp(args[0], "maxcomprate")) {
1016 if (*(args[1]) == 0) {
1017 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.comp_rate_lim = atoi(args[1]) * 1024;
1022 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001023 else if (!strcmp(args[0], "maxpipes")) {
1024 if (global.maxpipes != 0) {
1025 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001026 err_code |= ERR_ALERT;
1027 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001028 }
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001033 }
1034 global.maxpipes = atol(args[1]);
1035 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001036 else if (!strcmp(args[0], "maxzlibmem")) {
1037 if (*(args[1]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
William Lallemande3a7d992012-11-20 11:25:20 +01001042 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001043 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001044 else if (!strcmp(args[0], "maxcompcpuusage")) {
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001051 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001052 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056}
1057
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 else if (!strcmp(args[0], "ulimit-n")) {
1059 if (global.rlimit_nofile != 0) {
1060 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 err_code |= ERR_ALERT;
1062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
1064 if (*(args[1]) == 0) {
1065 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 global.rlimit_nofile = atol(args[1]);
1070 }
1071 else if (!strcmp(args[0], "chroot")) {
1072 if (global.chroot != NULL) {
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 a directory as an 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.chroot = strdup(args[1]);
1083 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001084 else if (!strcmp(args[0], "description")) {
1085 int i, len=0;
1086 char *d;
1087
1088 if (!*args[1]) {
1089 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1090 file, linenum, args[0]);
1091 err_code |= ERR_ALERT | ERR_FATAL;
1092 goto out;
1093 }
1094
Willy Tarreau348acfe2014-04-14 15:00:39 +02001095 for (i = 1; *args[i]; i++)
1096 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097
1098 if (global.desc)
1099 free(global.desc);
1100
1101 global.desc = d = (char *)calloc(1, len);
1102
Willy Tarreau348acfe2014-04-14 15:00:39 +02001103 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1104 for (i = 2; *args[i]; i++)
1105 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001106 }
1107 else if (!strcmp(args[0], "node")) {
1108 int i;
1109 char c;
1110
1111 for (i=0; args[1][i]; i++) {
1112 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001113 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1114 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001115 break;
1116 }
1117
1118 if (!i || args[1][i]) {
1119 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1120 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1121 file, linenum, args[0]);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
1124 }
1125
1126 if (global.node)
1127 free(global.node);
1128
1129 global.node = strdup(args[1]);
1130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 else if (!strcmp(args[0], "pidfile")) {
1132 if (global.pidfile != NULL) {
1133 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001134 err_code |= ERR_ALERT;
1135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 global.pidfile = strdup(args[1]);
1143 }
Emeric Bruned760922010-10-22 17:59:25 +02001144 else if (!strcmp(args[0], "unix-bind")) {
1145 int cur_arg = 1;
1146 while (*(args[cur_arg])) {
1147 if (!strcmp(args[cur_arg], "prefix")) {
1148 if (global.unix_bind.prefix != NULL) {
1149 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1150 err_code |= ERR_ALERT;
1151 cur_arg += 2;
1152 continue;
1153 }
1154
1155 if (*(args[cur_arg+1]) == 0) {
1156 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1161 cur_arg += 2;
1162 continue;
1163 }
1164
1165 if (!strcmp(args[cur_arg], "mode")) {
1166
1167 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1168 cur_arg += 2;
1169 continue;
1170 }
1171
1172 if (!strcmp(args[cur_arg], "uid")) {
1173
1174 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1175 cur_arg += 2;
1176 continue;
1177 }
1178
1179 if (!strcmp(args[cur_arg], "gid")) {
1180
1181 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1182 cur_arg += 2;
1183 continue;
1184 }
1185
1186 if (!strcmp(args[cur_arg], "user")) {
1187 struct passwd *user;
1188
1189 user = getpwnam(args[cur_arg + 1]);
1190 if (!user) {
1191 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1192 file, linenum, args[0], args[cur_arg + 1 ]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196
1197 global.unix_bind.ux.uid = user->pw_uid;
1198 cur_arg += 2;
1199 continue;
1200 }
1201
1202 if (!strcmp(args[cur_arg], "group")) {
1203 struct group *group;
1204
1205 group = getgrnam(args[cur_arg + 1]);
1206 if (!group) {
1207 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1208 file, linenum, args[0], args[cur_arg + 1 ]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212
1213 global.unix_bind.ux.gid = group->gr_gid;
1214 cur_arg += 2;
1215 continue;
1216 }
1217
Willy Tarreaub48f9582011-09-05 01:17:06 +02001218 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001219 file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 }
William Lallemand0f99e342011-10-12 17:50:54 +02001224 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1225 /* delete previous herited or defined syslog servers */
1226 struct logsrv *back;
1227 struct logsrv *tmp;
1228
1229 if (*(args[1]) != 0) {
1230 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234
1235 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1236 LIST_DEL(&tmp->list);
1237 free(tmp);
1238 }
1239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001241 struct sockaddr_storage *sk;
1242 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001243 struct logsrv *logsrv;
1244
Willy Tarreaubaaee002006-06-26 02:48:02 +02001245 if (*(args[1]) == 0 || *(args[2]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 }
William Lallemand0f99e342011-10-12 17:50:54 +02001250
1251 logsrv = calloc(1, sizeof(struct logsrv));
1252
1253 logsrv->facility = get_log_facility(args[2]);
1254 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001257 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259
William Lallemand0f99e342011-10-12 17:50:54 +02001260 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001262 logsrv->level = get_log_level(args[3]);
1263 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001266 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268 }
1269
William Lallemand0f99e342011-10-12 17:50:54 +02001270 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001271 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001272 logsrv->minlvl = get_log_level(args[4]);
1273 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001274 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001276 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001277 }
1278 }
1279
Willy Tarreau902636f2013-03-10 19:44:48 +01001280 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001281 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001282 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001283 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001284 free(logsrv);
1285 goto out;
1286 }
1287 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001288
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001289 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001290 if (port1 != port2) {
1291 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1292 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001293 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001294 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001295 goto out;
1296 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001297
William Lallemand0f99e342011-10-12 17:50:54 +02001298 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001299 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001300 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302
William Lallemand0f99e342011-10-12 17:50:54 +02001303 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001304 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001305 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1306 char *name;
1307 int len;
1308
1309 if (global.log_send_hostname != NULL) {
1310 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT;
1312 goto out;
1313 }
1314
1315 if (*(args[1]))
1316 name = args[1];
1317 else
1318 name = hostname;
1319
1320 len = strlen(name);
1321
1322 /* We'll add a space after the name to respect the log format */
1323 free(global.log_send_hostname);
1324 global.log_send_hostname = malloc(len + 2);
1325 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1326 }
Kevinm48936af2010-12-22 16:08:21 +00001327 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1328 if (*(args[1]) == 0) {
1329 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333 free(global.log_tag);
1334 global.log_tag = strdup(args[1]);
1335 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001336 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1337 if (global.spread_checks != 0) {
1338 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001339 err_code |= ERR_ALERT;
1340 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001341 }
1342 if (*(args[1]) == 0) {
1343 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001346 }
1347 global.spread_checks = atol(args[1]);
1348 if (global.spread_checks < 0 || global.spread_checks > 50) {
1349 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001353 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1354 const char *err;
1355 unsigned int val;
1356
1357
1358 if (*(args[1]) == 0) {
1359 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
1362 }
1363
1364 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1365 if (err) {
1366 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 }
1369 global.max_spread_checks = val;
1370 if (global.max_spread_checks < 0) {
1371 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1372 err_code |= ERR_ALERT | ERR_FATAL;
1373 }
1374 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001375 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1376#ifdef USE_CPU_AFFINITY
1377 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001378 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001379 unsigned long cpus = 0;
1380
1381 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001382 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001383 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001384 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001385 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001386 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001387 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001388 proc = atol(args[1]);
1389 if (proc >= 1 && proc <= LONGBITS)
1390 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001391 }
1392
1393 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001394 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",
1395 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
1398 }
1399
1400 cur_arg = 2;
1401 while (*args[cur_arg]) {
1402 unsigned int low, high;
1403
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001404 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001405 char *dash = strchr(args[cur_arg], '-');
1406
1407 low = high = str2uic(args[cur_arg]);
1408 if (dash)
1409 high = str2uic(dash + 1);
1410
1411 if (high < low) {
1412 unsigned int swap = low;
1413 low = high;
1414 high = swap;
1415 }
1416
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001417 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001418 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001419 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
1422 }
1423
1424 while (low <= high)
1425 cpus |= 1UL << low++;
1426 }
1427 else {
1428 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1429 file, linenum, args[0], args[cur_arg]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433 cur_arg++;
1434 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001435 for (i = 0; i < LONGBITS; i++)
1436 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001437 global.cpu_map[i] = cpus;
1438#else
1439 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
1442#endif
1443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001445 struct cfg_kw_list *kwl;
1446 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001447 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001448
1449 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1450 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1451 if (kwl->kw[index].section != CFG_GLOBAL)
1452 continue;
1453 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001454 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001455 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001456 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001458 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001459 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001460 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 err_code |= ERR_WARN;
1462 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001463 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001464 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001465 }
1466 }
1467 }
1468
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001472
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001474 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001475 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476}
1477
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001478void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001480 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 defproxy.mode = PR_MODE_TCP;
1482 defproxy.state = PR_STNEW;
1483 defproxy.maxconn = cfg_maxpconn;
1484 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001485
Simon Horman66183002013-02-23 10:16:43 +09001486 defproxy.defsrv.check.inter = DEF_CHKINTR;
1487 defproxy.defsrv.check.fastinter = 0;
1488 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001489 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1490 defproxy.defsrv.agent.fastinter = 0;
1491 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001492 defproxy.defsrv.check.rise = DEF_RISETIME;
1493 defproxy.defsrv.check.fall = DEF_FALLTIME;
1494 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1495 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001496 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001497 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001498 defproxy.defsrv.maxqueue = 0;
1499 defproxy.defsrv.minconn = 0;
1500 defproxy.defsrv.maxconn = 0;
1501 defproxy.defsrv.slowstart = 0;
1502 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1503 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1504 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505}
1506
Willy Tarreauade5ec42010-01-28 19:33:49 +01001507
1508static int create_cond_regex_rule(const char *file, int line,
1509 struct proxy *px, int dir, int action, int flags,
1510 const char *cmd, const char *reg, const char *repl,
1511 const char **cond_start)
1512{
1513 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001514 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001515 const char *err;
1516 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001517 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001518
1519 if (px == &defproxy) {
1520 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto err;
1523 }
1524
1525 if (*reg == 0) {
1526 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto err;
1529 }
1530
1531 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1532 err_code |= ERR_WARN;
1533
Willy Tarreau5321c422010-01-28 20:35:13 +01001534 if (cond_start &&
1535 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001536 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1537 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1538 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto err;
1541 }
1542 }
1543 else if (cond_start && **cond_start) {
1544 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1545 file, line, cmd, *cond_start);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto err;
1548 }
1549
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001550 err_code |= warnif_cond_conflicts(cond,
1551 (dir == SMP_OPT_DIR_REQ) ?
1552 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1553 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1554 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001555
Willy Tarreauade5ec42010-01-28 19:33:49 +01001556 preg = calloc(1, sizeof(regex_t));
1557 if (!preg) {
1558 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1559 err_code = ERR_ALERT | ERR_FATAL;
1560 goto err;
1561 }
1562
1563 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1564 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1565 err_code = ERR_ALERT | ERR_FATAL;
1566 goto err;
1567 }
1568
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001569 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001570 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001571 if (repl && err) {
1572 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1573 file, line, cmd, *err);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto err;
1576 }
1577
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001578 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001579 err_code |= ERR_WARN;
1580
Willy Tarreauf4068b62012-05-08 17:37:49 +02001581 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001582 return err_code;
1583 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001584 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001585 free(preg);
1586 return err_code;
1587}
1588
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001591 * Returns the error code, 0 if OK, or any combination of :
1592 * - ERR_ABORT: must abort ASAP
1593 * - ERR_FATAL: we can continue parsing but not start the service
1594 * - ERR_WARN: a warning has been emitted
1595 * - ERR_ALERT: an alert has been emitted
1596 * Only the two first ones can stop processing, the two others are just
1597 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001599int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1600{
1601 static struct peers *curpeers = NULL;
1602 struct peer *newpeer = NULL;
1603 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001604 struct bind_conf *bind_conf;
1605 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001606 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001607 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001608
1609 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001610 if (!*args[1]) {
1611 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001612 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001613 goto out;
1614 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001615
1616 err = invalid_char(args[1]);
1617 if (err) {
1618 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1619 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001620 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001621 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001622 }
1623
1624 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1625 /*
1626 * If there are two proxies with the same name only following
1627 * combinations are allowed:
1628 */
1629 if (strcmp(curpeers->id, args[1]) == 0) {
1630 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1631 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1632 err_code |= ERR_WARN;
1633 }
1634 }
1635
1636 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1637 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1638 err_code |= ERR_ALERT | ERR_ABORT;
1639 goto out;
1640 }
1641
1642 curpeers->next = peers;
1643 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001644 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 curpeers->conf.line = linenum;
1646 curpeers->last_change = now.tv_sec;
1647 curpeers->id = strdup(args[1]);
1648 }
1649 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001650 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001651 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001652 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001653
1654 if (!*args[2]) {
1655 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1656 file, linenum, args[0]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660
1661 err = invalid_char(args[1]);
1662 if (err) {
1663 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1664 file, linenum, *err, args[1]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667 }
1668
1669 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1670 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1671 err_code |= ERR_ALERT | ERR_ABORT;
1672 goto out;
1673 }
1674
1675 /* the peers are linked backwards first */
1676 curpeers->count++;
1677 newpeer->next = curpeers->remote;
1678 curpeers->remote = newpeer;
1679 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001680 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001681 newpeer->conf.line = linenum;
1682
1683 newpeer->last_change = now.tv_sec;
1684 newpeer->id = strdup(args[1]);
1685
Willy Tarreau902636f2013-03-10 19:44:48 +01001686 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001687 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001688 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001691 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001692
1693 proto = protocol_by_family(sk->ss_family);
1694 if (!proto || !proto->connect) {
1695 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1696 file, linenum, args[0], args[1]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001700
1701 if (port1 != port2) {
1702 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1703 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
Willy Tarreau2aa38802013-02-20 19:20:59 +01001708 if (!port1) {
1709 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1710 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
1713 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001714
Emeric Brun32da3c42010-09-23 18:39:19 +02001715 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001716 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001717 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001718 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001719
Emeric Brun32da3c42010-09-23 18:39:19 +02001720 if (strcmp(newpeer->id, localpeer) == 0) {
1721 /* Current is local peer, it define a frontend */
1722 newpeer->local = 1;
1723
1724 if (!curpeers->peers_fe) {
1725 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1726 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1727 err_code |= ERR_ALERT | ERR_ABORT;
1728 goto out;
1729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001730
Willy Tarreau237250c2011-07-29 01:49:03 +02001731 init_new_proxy(curpeers->peers_fe);
1732 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001733
1734 curpeers->peers_fe->last_change = now.tv_sec;
1735 curpeers->peers_fe->id = strdup(args[1]);
1736 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001737 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001738 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1739 curpeers->peers_fe->timeout.connect = 5000;
1740 curpeers->peers_fe->accept = peer_accept;
1741 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001742 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1743 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001744
1745 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1746
Willy Tarreau902636f2013-03-10 19:44:48 +01001747 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1748 if (errmsg && *errmsg) {
1749 indent_msg(&errmsg, 2);
1750 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001751 }
1752 else
1753 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1754 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001755 err_code |= ERR_FATAL;
1756 goto out;
1757 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001758
1759 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001760 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001761 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1762 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1763 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1764 l->accept = session_accept;
1765 l->handler = process_session;
1766 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1767 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1768 global.maxsock += l->maxconn;
1769 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001770 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001771 else {
1772 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1773 file, linenum, args[0], args[1],
1774 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1775 err_code |= ERR_FATAL;
1776 goto out;
1777 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001778 }
1779 } /* neither "peer" nor "peers" */
1780 else if (*args[0] != 0) {
1781 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
1786out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001787 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001788 return err_code;
1789}
1790
Willy Tarreau3842f002009-06-14 11:39:52 +02001791int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792{
1793 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001794 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001795 int rc;
1796 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001797 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001798 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001799 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001800 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001801 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802
Willy Tarreau977b8e42006-12-29 14:19:17 +01001803 if (!strcmp(args[0], "listen"))
1804 rc = PR_CAP_LISTEN;
1805 else if (!strcmp(args[0], "frontend"))
1806 rc = PR_CAP_FE | PR_CAP_RS;
1807 else if (!strcmp(args[0], "backend"))
1808 rc = PR_CAP_BE | PR_CAP_RS;
1809 else if (!strcmp(args[0], "ruleset"))
1810 rc = PR_CAP_RS;
1811 else
1812 rc = PR_CAP_NONE;
1813
1814 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001815 struct ebpt_node *node;
1816
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 if (!*args[1]) {
1818 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1819 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_ABORT;
1822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001824
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001825 err = invalid_char(args[1]);
1826 if (err) {
1827 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1828 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001829 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001830 }
1831
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001832 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1833 curproxy = container_of(node, struct proxy, conf.by_name);
1834
1835 if (strcmp(curproxy->id, args[1]) != 0)
1836 break;
1837
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001838 /*
1839 * If there are two proxies with the same name only following
1840 * combinations are allowed:
1841 *
1842 * listen backend frontend ruleset
1843 * listen - - - -
1844 * backend - - OK -
1845 * frontend - OK - -
1846 * ruleset - - - -
1847 */
1848
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001849 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1850 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001851 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1852 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1853 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001854 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001855 }
1856 }
1857
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1859 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_ABORT;
1861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001863
Willy Tarreau97cb7802010-01-03 20:23:58 +01001864 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->next = proxy;
1866 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001867 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1868 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001869 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001871 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001872 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873
1874 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001875 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001876 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001877
Willy Tarreau4348fad2012-09-20 16:48:07 +02001878 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1879
Willy Tarreau902636f2013-03-10 19:44:48 +01001880 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1881 if (errmsg && *errmsg) {
1882 indent_msg(&errmsg, 2);
1883 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001884 }
1885 else
1886 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1887 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_FATAL;
1889 goto out;
1890 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001891
Willy Tarreau4348fad2012-09-20 16:48:07 +02001892 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001893 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
1896
1897 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001898 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001899 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001903 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001904 curproxy->no_options = defproxy.no_options;
1905 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001906 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001907 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001908 curproxy->except_net = defproxy.except_net;
1909 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001910 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001911 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001913 if (defproxy.fwdfor_hdr_len) {
1914 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1915 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1916 }
1917
Willy Tarreaub86db342009-11-30 11:50:16 +01001918 if (defproxy.orgto_hdr_len) {
1919 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1920 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1921 }
1922
Mark Lamourinec2247f02012-01-04 13:02:01 -05001923 if (defproxy.server_id_hdr_len) {
1924 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1925 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1926 }
1927
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 if (curproxy->cap & PR_CAP_FE) {
1929 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001930 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001931 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932
1933 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001934 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1935 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
1937 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 if (curproxy->cap & PR_CAP_BE) {
1941 curproxy->fullconn = defproxy.fullconn;
1942 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001943 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001945 if (defproxy.check_req) {
1946 curproxy->check_req = calloc(1, defproxy.check_len);
1947 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1948 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001949 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001951 if (defproxy.expect_str) {
1952 curproxy->expect_str = strdup(defproxy.expect_str);
1953 if (defproxy.expect_regex) {
1954 /* note: this regex is known to be valid */
1955 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1956 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1957 }
1958 }
1959
Willy Tarreau67402132012-05-31 20:40:20 +02001960 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001961 if (defproxy.cookie_name)
1962 curproxy->cookie_name = strdup(defproxy.cookie_name);
1963 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001964 if (defproxy.cookie_domain)
1965 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001966
Willy Tarreau31936852010-10-06 16:59:56 +02001967 if (defproxy.cookie_maxidle)
1968 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1969
1970 if (defproxy.cookie_maxlife)
1971 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1972
Emeric Brun647caf12009-06-30 17:57:00 +02001973 if (defproxy.rdp_cookie_name)
1974 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1975 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1976
Willy Tarreau01732802007-11-01 22:48:15 +01001977 if (defproxy.url_param_name)
1978 curproxy->url_param_name = strdup(defproxy.url_param_name);
1979 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001980
Benoitaffb4812009-03-25 13:02:10 +01001981 if (defproxy.hh_name)
1982 curproxy->hh_name = strdup(defproxy.hh_name);
1983 curproxy->hh_len = defproxy.hh_len;
1984 curproxy->hh_match_domain = defproxy.hh_match_domain;
1985
Willy Tarreauef9a3602012-12-08 22:29:20 +01001986 if (defproxy.conn_src.iface_name)
1987 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1988 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001989 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001990#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001991 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001992#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001995 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996 if (defproxy.capture_name)
1997 curproxy->capture_name = strdup(defproxy.capture_name);
1998 curproxy->capture_namelen = defproxy.capture_namelen;
1999 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002000 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002003 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002004 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002005 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002006 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002007 curproxy->mon_net = defproxy.mon_net;
2008 curproxy->mon_mask = defproxy.mon_mask;
2009 if (defproxy.monitor_uri)
2010 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2011 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002012 if (defproxy.defbe.name)
2013 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002014
2015 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002016 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2017 if (curproxy->conf.logformat_string &&
2018 curproxy->conf.logformat_string != default_http_log_format &&
2019 curproxy->conf.logformat_string != default_tcp_log_format &&
2020 curproxy->conf.logformat_string != clf_http_log_format)
2021 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2022
2023 if (defproxy.conf.lfs_file) {
2024 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2025 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2026 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027 }
2028
2029 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002030 curproxy->timeout.connect = defproxy.timeout.connect;
2031 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002032 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002033 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002034 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002035 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002036 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002037 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002038 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 }
2040
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002042 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002043
2044 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002045 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002046 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002047 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002048 LIST_INIT(&node->list);
2049 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2050 }
2051
Willy Tarreau62a61232013-04-12 18:13:46 +02002052 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2053 if (curproxy->conf.uniqueid_format_string)
2054 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2055
2056 if (defproxy.conf.uif_file) {
2057 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2058 curproxy->conf.uif_line = defproxy.conf.uif_line;
2059 }
William Lallemanda73203e2012-03-12 12:48:57 +01002060
2061 /* copy default header unique id */
2062 if (defproxy.header_unique_id)
2063 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2064
William Lallemand82fe75c2012-10-23 10:25:10 +02002065 /* default compression options */
2066 if (defproxy.comp != NULL) {
2067 curproxy->comp = calloc(1, sizeof(struct comp));
2068 curproxy->comp->algos = defproxy.comp->algos;
2069 curproxy->comp->types = defproxy.comp->types;
2070 }
2071
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002073 curproxy->conf.used_listener_id = EB_ROOT;
2074 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002075
Willy Tarreau93893792009-07-23 13:19:11 +02002076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
2078 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2079 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002080 /* FIXME-20070101: we should do this too at the end of the
2081 * config parsing to free all default values.
2082 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002083 free(defproxy.check_req);
2084 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002085 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002086 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002087 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002088 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(defproxy.capture_name);
2090 free(defproxy.monitor_uri);
2091 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002092 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002093 free(defproxy.fwdfor_hdr_name);
2094 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002095 free(defproxy.orgto_hdr_name);
2096 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002097 free(defproxy.server_id_hdr_name);
2098 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002099 free(defproxy.expect_str);
2100 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002101
Willy Tarreau62a61232013-04-12 18:13:46 +02002102 if (defproxy.conf.logformat_string != default_http_log_format &&
2103 defproxy.conf.logformat_string != default_tcp_log_format &&
2104 defproxy.conf.logformat_string != clf_http_log_format)
2105 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002106
Willy Tarreau62a61232013-04-12 18:13:46 +02002107 free(defproxy.conf.uniqueid_format_string);
2108 free(defproxy.conf.lfs_file);
2109 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002110
Willy Tarreaua534fea2008-08-03 12:19:50 +02002111 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002112 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002113
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 /* we cannot free uri_auth because it might already be used */
2115 init_default_instance();
2116 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002117 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2118 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002119 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 }
2122 else if (curproxy == NULL) {
2123 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_ALERT | ERR_FATAL;
2125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002127
2128 /* update the current file and line being parsed */
2129 curproxy->conf.args.file = curproxy->conf.file;
2130 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131
2132 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002133 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2134 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2135 if (err_code & ERR_FATAL)
2136 goto out;
2137 }
2138 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002139 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002140 int cur_arg;
2141
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 if (curproxy == &defproxy) {
2143 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149
Willy Tarreau24709282013-03-10 21:32:12 +01002150 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002151 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002156
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002157 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002158
2159 /* use default settings for unix sockets */
2160 bind_conf->ux.uid = global.unix_bind.ux.uid;
2161 bind_conf->ux.gid = global.unix_bind.ux.gid;
2162 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002163
2164 /* NOTE: the following line might create several listeners if there
2165 * are comma-separated IPs or port ranges. So all further processing
2166 * will have to be applied to all listeners created after last_listen.
2167 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002168 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2169 if (errmsg && *errmsg) {
2170 indent_msg(&errmsg, 2);
2171 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002172 }
2173 else
2174 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2175 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002179
Willy Tarreau4348fad2012-09-20 16:48:07 +02002180 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2181 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002182 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002183 }
2184
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002185 cur_arg = 2;
2186 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002187 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002188 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002189 char *err;
2190
Willy Tarreau26982662012-09-12 23:17:10 +02002191 kw = bind_find_kw(args[cur_arg]);
2192 if (kw) {
2193 char *err = NULL;
2194 int code;
2195
2196 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002197 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2198 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002199 cur_arg += 1 + kw->skip ;
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Willy Tarreau4348fad2012-09-20 16:48:07 +02002204 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002205 err_code |= code;
2206
2207 if (code) {
2208 if (err && *err) {
2209 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002210 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002211 }
2212 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002213 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2214 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002215 if (code & ERR_FATAL) {
2216 free(err);
2217 cur_arg += 1 + kw->skip;
2218 goto out;
2219 }
2220 }
2221 free(err);
2222 cur_arg += 1 + kw->skip;
2223 continue;
2224 }
2225
Willy Tarreau8638f482012-09-18 18:01:17 +02002226 err = NULL;
2227 if (!bind_dumped) {
2228 bind_dump_kws(&err);
2229 indent_msg(&err, 4);
2230 bind_dumped = 1;
2231 }
2232
2233 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2234 file, linenum, args[0], args[1], args[cur_arg],
2235 err ? " Registered keywords :" : "", err ? err : "");
2236 free(err);
2237
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002240 }
Willy Tarreau93893792009-07-23 13:19:11 +02002241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002244 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 /* flush useless bits */
2254 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002257 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002260
Willy Tarreau1c47f852006-07-09 08:22:27 +02002261 if (!*args[1]) {
2262 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002266 }
2267
Willy Tarreaua534fea2008-08-03 12:19:50 +02002268 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002269 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002270 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002271 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002272 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2273
Willy Tarreau93893792009-07-23 13:19:11 +02002274 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2277 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2278 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2279 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2280 else {
2281 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 }
2285 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002286 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002287 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002288
2289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2291 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002294 }
2295
2296 if (!*args[1]) {
2297 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002301 }
2302
2303 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002304 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002305
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002306 if (curproxy->uuid <= 0) {
2307 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002308 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002311 }
2312
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002313 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2314 if (node) {
2315 struct proxy *target = container_of(node, struct proxy, conf.id);
2316 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2317 file, linenum, proxy_type_str(curproxy), curproxy->id,
2318 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002323 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002324 else if (!strcmp(args[0], "description")) {
2325 int i, len=0;
2326 char *d;
2327
Cyril Bonté99ed3272010-01-24 23:29:44 +01002328 if (curproxy == &defproxy) {
2329 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2330 file, linenum, args[0]);
2331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
2333 }
2334
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002335 if (!*args[1]) {
2336 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2337 file, linenum, args[0]);
2338 return -1;
2339 }
2340
Willy Tarreau348acfe2014-04-14 15:00:39 +02002341 for (i = 1; *args[i]; i++)
2342 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002343
2344 d = (char *)calloc(1, len);
2345 curproxy->desc = d;
2346
Willy Tarreau348acfe2014-04-14 15:00:39 +02002347 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2348 for (i = 2; *args[i]; i++)
2349 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002350
2351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2353 curproxy->state = PR_STSTOPPED;
2354 }
2355 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2356 curproxy->state = PR_STNEW;
2357 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002358 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2359 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002360 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002361
2362 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002363 unsigned int low, high;
2364
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002365 if (strcmp(args[cur_arg], "all") == 0) {
2366 set = 0;
2367 break;
2368 }
2369 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002370 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002371 }
2372 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002373 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002374 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002375 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002376 char *dash = strchr(args[cur_arg], '-');
2377
2378 low = high = str2uic(args[cur_arg]);
2379 if (dash)
2380 high = str2uic(dash + 1);
2381
2382 if (high < low) {
2383 unsigned int swap = low;
2384 low = high;
2385 high = swap;
2386 }
2387
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002388 if (low < 1 || high > LONGBITS) {
2389 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2390 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002393 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002394 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002395 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002396 }
2397 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002398 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2399 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002402 }
2403 cur_arg++;
2404 }
2405 curproxy->bind_proc = set;
2406 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002407 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002408 if (curproxy == &defproxy) {
2409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002412 }
2413
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002414 err = invalid_char(args[1]);
2415 if (err) {
2416 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2417 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002419 }
2420
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002421 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002422 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2423 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002426 }
2427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2429 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430
Willy Tarreau977b8e42006-12-29 14:19:17 +01002431 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 if (*(args[1]) == 0) {
2435 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2436 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002440
Willy Tarreau67402132012-05-31 20:40:20 +02002441 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002442 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002443 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002444 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 curproxy->cookie_name = strdup(args[1]);
2446 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 cur_arg = 2;
2449 while (*(args[cur_arg])) {
2450 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002451 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002454 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002457 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002460 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002463 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002465 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002466 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002469 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002471 else if (!strcmp(args[cur_arg], "httponly")) {
2472 curproxy->ck_opts |= PR_CK_HTTPONLY;
2473 }
2474 else if (!strcmp(args[cur_arg], "secure")) {
2475 curproxy->ck_opts |= PR_CK_SECURE;
2476 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002477 else if (!strcmp(args[cur_arg], "domain")) {
2478 if (!*args[cur_arg + 1]) {
2479 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2480 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002483 }
2484
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002485 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002486 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002487 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2488 " dots nor does not start with a dot."
2489 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002490 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002491 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002492 }
2493
2494 err = invalid_domainchar(args[cur_arg + 1]);
2495 if (err) {
2496 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2497 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002500 }
2501
Willy Tarreau68a897b2009-12-03 23:28:34 +01002502 if (!curproxy->cookie_domain) {
2503 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2504 } else {
2505 /* one domain was already specified, add another one by
2506 * building the string which will be returned along with
2507 * the cookie.
2508 */
2509 char *new_ptr;
2510 int new_len = strlen(curproxy->cookie_domain) +
2511 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2512 new_ptr = malloc(new_len);
2513 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2514 free(curproxy->cookie_domain);
2515 curproxy->cookie_domain = new_ptr;
2516 }
Willy Tarreau31936852010-10-06 16:59:56 +02002517 cur_arg++;
2518 }
2519 else if (!strcmp(args[cur_arg], "maxidle")) {
2520 unsigned int maxidle;
2521 const char *res;
2522
2523 if (!*args[cur_arg + 1]) {
2524 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2525 file, linenum, args[cur_arg]);
2526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
2528 }
2529
2530 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2531 if (res) {
2532 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2533 file, linenum, *res, args[cur_arg]);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537 curproxy->cookie_maxidle = maxidle;
2538 cur_arg++;
2539 }
2540 else if (!strcmp(args[cur_arg], "maxlife")) {
2541 unsigned int maxlife;
2542 const char *res;
2543
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2546 file, linenum, args[cur_arg]);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2552 if (res) {
2553 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2554 file, linenum, *res, args[cur_arg]);
2555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
2558 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002559 cur_arg++;
2560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002562 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 +02002563 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
2567 cur_arg++;
2568 }
Willy Tarreau67402132012-05-31 20:40:20 +02002569 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2571 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574
Willy Tarreau67402132012-05-31 20:40:20 +02002575 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2577 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002580
Willy Tarreau67402132012-05-31 20:40:20 +02002581 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002582 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2583 file, linenum);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002587 else if (!strcmp(args[0], "persist")) { /* persist */
2588 if (*(args[1]) == 0) {
2589 Alert("parsing [%s:%d] : missing persist method.\n",
2590 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002593 }
2594
2595 if (!strncmp(args[1], "rdp-cookie", 10)) {
2596 curproxy->options2 |= PR_O2_RDPC_PRST;
2597
Emeric Brunb982a3d2010-01-04 15:45:53 +01002598 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002599 const char *beg, *end;
2600
2601 beg = args[1] + 11;
2602 end = strchr(beg, ')');
2603
2604 if (!end || end == beg) {
2605 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2606 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002609 }
2610
2611 free(curproxy->rdp_cookie_name);
2612 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2613 curproxy->rdp_cookie_len = end-beg;
2614 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002615 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002616 free(curproxy->rdp_cookie_name);
2617 curproxy->rdp_cookie_name = strdup("msts");
2618 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2619 }
2620 else { /* syntax */
2621 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2622 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002625 }
2626 }
2627 else {
2628 Alert("parsing [%s:%d] : unknown persist method.\n",
2629 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002632 }
2633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002635 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002637 if (curproxy == &defproxy) {
2638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642
Willy Tarreau977b8e42006-12-29 14:19:17 +01002643 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002647 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 }
2652 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002653 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 curproxy->appsession_name = strdup(args[1]);
2655 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2656 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002657 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2658 if (err) {
2659 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2660 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002663 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002664 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002665
Willy Tarreau51041c72007-09-09 21:56:53 +02002666 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2667 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_ABORT;
2669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002671
2672 cur_arg = 6;
2673 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002674 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2675 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002676 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002677 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002678 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002679 } else if (!strcmp(args[cur_arg], "prefix")) {
2680 curproxy->options2 |= PR_O2_AS_PFX;
2681 } else if (!strcmp(args[cur_arg], "mode")) {
2682 if (!*args[cur_arg + 1]) {
2683 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2684 file, linenum, args[0], args[cur_arg]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688
2689 cur_arg++;
2690 if (!strcmp(args[cur_arg], "query-string")) {
2691 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2692 curproxy->options2 |= PR_O2_AS_M_QS;
2693 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2694 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2695 curproxy->options2 |= PR_O2_AS_M_PP;
2696 } else {
2697 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
2700 }
2701 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002702 cur_arg++;
2703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 } /* Url App Session */
2705 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002706 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002708
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002710 if (curproxy == &defproxy) {
2711 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 if (*(args[4]) == 0) {
2717 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002722 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 curproxy->capture_name = strdup(args[2]);
2724 curproxy->capture_namelen = strlen(curproxy->capture_name);
2725 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 curproxy->to_log |= LW_COOKIE;
2727 }
2728 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2729 struct cap_hdr *hdr;
2730
2731 if (curproxy == &defproxy) {
2732 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 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 }
2736
2737 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2738 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2739 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
2743
2744 hdr = calloc(sizeof(struct cap_hdr), 1);
2745 hdr->next = curproxy->req_cap;
2746 hdr->name = strdup(args[3]);
2747 hdr->namelen = strlen(args[3]);
2748 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002749 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 hdr->index = curproxy->nb_req_cap++;
2751 curproxy->req_cap = hdr;
2752 curproxy->to_log |= LW_REQHDR;
2753 }
2754 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2755 struct cap_hdr *hdr;
2756
2757 if (curproxy == &defproxy) {
2758 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 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
2762
2763 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2764 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2765 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
2769 hdr = calloc(sizeof(struct cap_hdr), 1);
2770 hdr->next = curproxy->rsp_cap;
2771 hdr->name = strdup(args[3]);
2772 hdr->namelen = strlen(args[3]);
2773 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002774 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 hdr->index = curproxy->nb_rsp_cap++;
2776 curproxy->rsp_cap = hdr;
2777 curproxy->to_log |= LW_RSPHDR;
2778 }
2779 else {
2780 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 }
2785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 if (*(args[1]) == 0) {
2791 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
2796 curproxy->conn_retries = atol(args[1]);
2797 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002798 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002799 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002800
2801 if (curproxy == &defproxy) {
2802 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
2806
Willy Tarreau20b0de52012-12-24 15:45:22 +01002807 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2808 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2809 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2810 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002811 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002812 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2813 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 +01002814 file, linenum, args[0]);
2815 err_code |= ERR_WARN;
2816 }
2817
Willy Tarreauff011f22011-01-06 17:51:27 +01002818 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002819
Willy Tarreauff011f22011-01-06 17:51:27 +01002820 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002821 err_code |= ERR_ALERT | ERR_ABORT;
2822 goto out;
2823 }
2824
Willy Tarreau5002f572014-04-23 01:32:02 +02002825 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002826 err_code |= warnif_cond_conflicts(rule->cond,
2827 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2828 file, linenum);
2829
Willy Tarreauff011f22011-01-06 17:51:27 +01002830 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002831 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002832 else if (!strcmp(args[0], "http-response")) { /* response access control */
2833 struct http_res_rule *rule;
2834
2835 if (curproxy == &defproxy) {
2836 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840
2841 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2842 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2843 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2844 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2845 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2846 file, linenum, args[0]);
2847 err_code |= ERR_WARN;
2848 }
2849
2850 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2851
2852 if (!rule) {
2853 err_code |= ERR_ALERT | ERR_ABORT;
2854 goto out;
2855 }
2856
2857 err_code |= warnif_cond_conflicts(rule->cond,
2858 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2859 file, linenum);
2860
2861 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2862 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002863 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2864 /* set the header name and length into the proxy structure */
2865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2866 err_code |= ERR_WARN;
2867
2868 if (!*args[1]) {
2869 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2870 file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 /* set the desired header name */
2876 free(curproxy->server_id_hdr_name);
2877 curproxy->server_id_hdr_name = strdup(args[1]);
2878 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2879 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002880 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002881 struct http_req_rule *rule;
2882
Willy Tarreaub099aca2008-10-12 17:26:37 +02002883 if (curproxy == &defproxy) {
2884 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002887 }
2888
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002889 /* emulate "block" using "http-request block". Since these rules are supposed to
2890 * be processed before all http-request rules, we put them into their own list
2891 * and will insert them at the end.
2892 */
2893 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2894 if (!rule) {
2895 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002896 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002897 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002898 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2899 err_code |= warnif_cond_conflicts(rule->cond,
2900 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2901 file, linenum);
2902 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002903
2904 if (!already_warned(WARN_BLOCK_DEPRECATED))
2905 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]);
2906
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002907 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002908 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002909 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002910
Cyril Bonté99ed3272010-01-24 23:29:44 +01002911 if (curproxy == &defproxy) {
2912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002917 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002918 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2919 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002922 }
2923
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002924 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002925 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002926 err_code |= warnif_cond_conflicts(rule->cond,
2927 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2928 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002929 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002930 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002931 struct switching_rule *rule;
2932
Willy Tarreaub099aca2008-10-12 17:26:37 +02002933 if (curproxy == &defproxy) {
2934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002937 }
2938
Willy Tarreau55ea7572007-06-17 19:56:27 +02002939 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002941
2942 if (*(args[1]) == 0) {
2943 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002946 }
2947
Willy Tarreauf51658d2014-04-23 01:21:56 +02002948 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2949 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2950 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2951 file, linenum, errmsg);
2952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002955
Willy Tarreauf51658d2014-04-23 01:21:56 +02002956 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002957 }
2958
2959 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2960 rule->cond = cond;
2961 rule->be.name = strdup(args[1]);
2962 LIST_INIT(&rule->list);
2963 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2964 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002965 else if (strcmp(args[0], "use-server") == 0) {
2966 struct server_rule *rule;
2967
2968 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
2974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2975 err_code |= ERR_WARN;
2976
2977 if (*(args[1]) == 0) {
2978 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2984 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2985 file, linenum, args[0]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002990 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2991 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2992 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002997 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002998
2999 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3000 rule->cond = cond;
3001 rule->srv.name = strdup(args[1]);
3002 LIST_INIT(&rule->list);
3003 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3004 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3005 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003006 else if ((!strcmp(args[0], "force-persist")) ||
3007 (!strcmp(args[0], "ignore-persist"))) {
3008 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003009
3010 if (curproxy == &defproxy) {
3011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
3014 }
3015
3016 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3017 err_code |= ERR_WARN;
3018
Willy Tarreauef6494c2010-01-28 17:12:36 +01003019 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003020 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3021 file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003026 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3027 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3028 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003033 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3034 * where force-persist is applied.
3035 */
3036 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003037
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003038 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003039 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003040 if (!strcmp(args[0], "force-persist")) {
3041 rule->type = PERSIST_TYPE_FORCE;
3042 } else {
3043 rule->type = PERSIST_TYPE_IGNORE;
3044 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003045 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003046 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 else if (!strcmp(args[0], "stick-table")) {
3049 int myidx = 1;
3050
Emeric Brun32da3c42010-09-23 18:39:19 +02003051 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003052 curproxy->table.type = (unsigned int)-1;
3053 while (*args[myidx]) {
3054 const char *err;
3055
3056 if (strcmp(args[myidx], "size") == 0) {
3057 myidx++;
3058 if (!*(args[myidx])) {
3059 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3060 file, linenum, args[myidx-1]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3065 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3066 file, linenum, *err, args[myidx-1]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003070 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003071 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003072 else if (strcmp(args[myidx], "peers") == 0) {
3073 myidx++;
Godbach50523162013-12-11 19:48:57 +08003074 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003075 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3076 file, linenum, args[myidx-1]);
3077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Godbach50523162013-12-11 19:48:57 +08003079 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003080 curproxy->table.peers.name = strdup(args[myidx++]);
3081 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003082 else if (strcmp(args[myidx], "expire") == 0) {
3083 myidx++;
3084 if (!*(args[myidx])) {
3085 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3086 file, linenum, args[myidx-1]);
3087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
3089 }
3090 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3091 if (err) {
3092 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3093 file, linenum, *err, args[myidx-1]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003098 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003099 }
3100 else if (strcmp(args[myidx], "nopurge") == 0) {
3101 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003102 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003103 }
3104 else if (strcmp(args[myidx], "type") == 0) {
3105 myidx++;
3106 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3107 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3108 file, linenum, args[myidx]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003112 /* myidx already points to next arg */
3113 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003114 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003115 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003116 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003117
3118 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003119 nw = args[myidx];
3120 while (*nw) {
3121 /* the "store" keyword supports a comma-separated list */
3122 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003123 sa = NULL; /* store arg */
3124 while (*nw && *nw != ',') {
3125 if (*nw == '(') {
3126 *nw = 0;
3127 sa = ++nw;
3128 while (*nw != ')') {
3129 if (!*nw) {
3130 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134 }
3135 nw++;
3136 }
3137 *nw = '\0';
3138 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003139 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003140 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003141 if (*nw)
3142 *nw++ = '\0';
3143 type = stktable_get_data_type(cw);
3144 if (type < 0) {
3145 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3146 file, linenum, args[0], cw);
3147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
3149 }
Willy Tarreauac782882010-06-20 10:41:54 +02003150
3151 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3152 switch (err) {
3153 case PE_NONE: break;
3154 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003155 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3156 file, linenum, args[0], cw);
3157 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003158 break;
3159
3160 case PE_ARG_MISSING:
3161 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3162 file, linenum, args[0], cw);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165
3166 case PE_ARG_NOT_USED:
3167 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3168 file, linenum, args[0], cw);
3169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
3171
3172 default:
3173 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3174 file, linenum, args[0], cw);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003177 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003178 }
3179 myidx++;
3180 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003181 else {
3182 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3183 file, linenum, args[myidx]);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003186 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003187 }
3188
3189 if (!curproxy->table.size) {
3190 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3191 file, linenum);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195
3196 if (curproxy->table.type == (unsigned int)-1) {
3197 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3198 file, linenum);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202 }
3203 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003204 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003205 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003206 int myidx = 0;
3207 const char *name = NULL;
3208 int flags;
3209
3210 if (curproxy == &defproxy) {
3211 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215
3216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3217 err_code |= ERR_WARN;
3218 goto out;
3219 }
3220
3221 myidx++;
3222 if ((strcmp(args[myidx], "store") == 0) ||
3223 (strcmp(args[myidx], "store-request") == 0)) {
3224 myidx++;
3225 flags = STK_IS_STORE;
3226 }
3227 else if (strcmp(args[myidx], "store-response") == 0) {
3228 myidx++;
3229 flags = STK_IS_STORE | STK_ON_RSP;
3230 }
3231 else if (strcmp(args[myidx], "match") == 0) {
3232 myidx++;
3233 flags = STK_IS_MATCH;
3234 }
3235 else if (strcmp(args[myidx], "on") == 0) {
3236 myidx++;
3237 flags = STK_IS_MATCH | STK_IS_STORE;
3238 }
3239 else {
3240 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
3243 }
3244
3245 if (*(args[myidx]) == 0) {
3246 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003251 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003252 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003253 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003254 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258
3259 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003260 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3261 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3262 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003264 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003265 goto out;
3266 }
3267 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003268 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3269 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3270 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003271 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003272 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003273 goto out;
3274 }
3275 }
3276
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003277 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003278 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003279
Emeric Brunb982a3d2010-01-04 15:45:53 +01003280 if (strcmp(args[myidx], "table") == 0) {
3281 myidx++;
3282 name = args[myidx++];
3283 }
3284
Willy Tarreauef6494c2010-01-28 17:12:36 +01003285 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003286 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3287 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3288 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003289 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003290 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003291 goto out;
3292 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003293 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003294 else if (*(args[myidx])) {
3295 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3296 file, linenum, args[0], args[myidx]);
3297 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003298 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003299 goto out;
3300 }
Emeric Brun97679e72010-09-23 17:56:44 +02003301 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003302 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003303 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003304 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003305
Emeric Brunb982a3d2010-01-04 15:45:53 +01003306 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3307 rule->cond = cond;
3308 rule->expr = expr;
3309 rule->flags = flags;
3310 rule->table.name = name ? strdup(name) : NULL;
3311 LIST_INIT(&rule->list);
3312 if (flags & STK_ON_RSP)
3313 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3314 else
3315 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 else if (!strcmp(args[0], "stats")) {
3318 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3319 curproxy->uri_auth = NULL; /* we must detach from the default config */
3320
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003321 if (!*args[1]) {
3322 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003323 } else if (!strcmp(args[1], "admin")) {
3324 struct stats_admin_rule *rule;
3325
3326 if (curproxy == &defproxy) {
3327 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331
3332 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3333 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3334 err_code |= ERR_ALERT | ERR_ABORT;
3335 goto out;
3336 }
3337
3338 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3339 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3340 file, linenum, args[0], args[1]);
3341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
3343 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003344 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3345 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3346 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003351 err_code |= warnif_cond_conflicts(cond,
3352 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3353 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003354
3355 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3356 rule->cond = cond;
3357 LIST_INIT(&rule->list);
3358 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 } else if (!strcmp(args[1], "uri")) {
3360 if (*(args[2]) == 0) {
3361 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3365 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_ABORT;
3367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 }
3369 } else if (!strcmp(args[1], "realm")) {
3370 if (*(args[2]) == 0) {
3371 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3375 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_ABORT;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003379 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003380 unsigned interval;
3381
3382 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3383 if (err) {
3384 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3385 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003388 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_ABORT;
3391 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003392 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003393 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003394 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003395
3396 if (curproxy == &defproxy) {
3397 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
3402 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3403 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3404 err_code |= ERR_ALERT | ERR_ABORT;
3405 goto out;
3406 }
3407
Willy Tarreauff011f22011-01-06 17:51:27 +01003408 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3409 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003410 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3411 file, linenum, args[0]);
3412 err_code |= ERR_WARN;
3413 }
3414
Willy Tarreauff011f22011-01-06 17:51:27 +01003415 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003416
Willy Tarreauff011f22011-01-06 17:51:27 +01003417 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003418 err_code |= ERR_ALERT | ERR_ABORT;
3419 goto out;
3420 }
3421
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003422 err_code |= warnif_cond_conflicts(rule->cond,
3423 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3424 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003425 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003426
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 } else if (!strcmp(args[1], "auth")) {
3428 if (*(args[2]) == 0) {
3429 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003434 err_code |= ERR_ALERT | ERR_ABORT;
3435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 }
3437 } else if (!strcmp(args[1], "scope")) {
3438 if (*(args[2]) == 0) {
3439 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3443 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003444 err_code |= ERR_ALERT | ERR_ABORT;
3445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003446 }
3447 } else if (!strcmp(args[1], "enable")) {
3448 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3449 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_ABORT;
3451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003453 } else if (!strcmp(args[1], "hide-version")) {
3454 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3455 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_ABORT;
3457 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003458 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003459 } else if (!strcmp(args[1], "show-legends")) {
3460 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3461 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3462 err_code |= ERR_ALERT | ERR_ABORT;
3463 goto out;
3464 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003465 } else if (!strcmp(args[1], "show-node")) {
3466
3467 if (*args[2]) {
3468 int i;
3469 char c;
3470
3471 for (i=0; args[2][i]; i++) {
3472 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003473 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3474 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003475 break;
3476 }
3477
3478 if (!i || args[2][i]) {
3479 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3480 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3481 file, linenum, args[0], args[1]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485 }
3486
3487 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3488 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3489 err_code |= ERR_ALERT | ERR_ABORT;
3490 goto out;
3491 }
3492 } else if (!strcmp(args[1], "show-desc")) {
3493 char *desc = NULL;
3494
3495 if (*args[2]) {
3496 int i, len=0;
3497 char *d;
3498
Willy Tarreau348acfe2014-04-14 15:00:39 +02003499 for (i = 2; *args[i]; i++)
3500 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003501
3502 desc = d = (char *)calloc(1, len);
3503
Willy Tarreau348acfe2014-04-14 15:00:39 +02003504 d += snprintf(d, desc + len - d, "%s", args[2]);
3505 for (i = 3; *args[i]; i++)
3506 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003507 }
3508
3509 if (!*args[2] && !global.desc)
3510 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3511 file, linenum, args[1]);
3512 else {
3513 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3514 free(desc);
3515 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3516 err_code |= ERR_ALERT | ERR_ABORT;
3517 goto out;
3518 }
3519 free(desc);
3520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003522stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003523 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 +01003524 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 }
3528 }
3529 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003530 int optnum;
3531
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003532 if (*(args[1]) == '\0') {
3533 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003538
3539 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3540 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003541 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3542 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3543 file, linenum, cfg_opts[optnum].name);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
Willy Tarreau93893792009-07-23 13:19:11 +02003547 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3548 err_code |= ERR_WARN;
3549 goto out;
3550 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003551
Willy Tarreau3842f002009-06-14 11:39:52 +02003552 curproxy->no_options &= ~cfg_opts[optnum].val;
3553 curproxy->options &= ~cfg_opts[optnum].val;
3554
3555 switch (kwm) {
3556 case KWM_STD:
3557 curproxy->options |= cfg_opts[optnum].val;
3558 break;
3559 case KWM_NO:
3560 curproxy->no_options |= cfg_opts[optnum].val;
3561 break;
3562 case KWM_DEF: /* already cleared */
3563 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003564 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003565
Willy Tarreau93893792009-07-23 13:19:11 +02003566 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003567 }
3568 }
3569
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003570 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3571 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003572 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3573 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3574 file, linenum, cfg_opts2[optnum].name);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
Willy Tarreau93893792009-07-23 13:19:11 +02003578 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3579 err_code |= ERR_WARN;
3580 goto out;
3581 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003582
Willy Tarreau3842f002009-06-14 11:39:52 +02003583 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3584 curproxy->options2 &= ~cfg_opts2[optnum].val;
3585
3586 switch (kwm) {
3587 case KWM_STD:
3588 curproxy->options2 |= cfg_opts2[optnum].val;
3589 break;
3590 case KWM_NO:
3591 curproxy->no_options2 |= cfg_opts2[optnum].val;
3592 break;
3593 case KWM_DEF: /* already cleared */
3594 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003595 }
Willy Tarreau93893792009-07-23 13:19:11 +02003596 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003597 }
3598 }
3599
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003600 /* HTTP options override each other. They can be cancelled using
3601 * "no option xxx" which only switches to default mode if the mode
3602 * was this one (useful for cancelling options set in defaults
3603 * sections).
3604 */
3605 if (strcmp(args[1], "httpclose") == 0) {
3606 if (kwm == KWM_STD) {
3607 curproxy->options &= ~PR_O_HTTP_MODE;
3608 curproxy->options |= PR_O_HTTP_PCL;
3609 goto out;
3610 }
3611 else if (kwm == KWM_NO) {
3612 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3613 curproxy->options &= ~PR_O_HTTP_MODE;
3614 goto out;
3615 }
3616 }
3617 else if (strcmp(args[1], "forceclose") == 0) {
3618 if (kwm == KWM_STD) {
3619 curproxy->options &= ~PR_O_HTTP_MODE;
3620 curproxy->options |= PR_O_HTTP_FCL;
3621 goto out;
3622 }
3623 else if (kwm == KWM_NO) {
3624 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3625 curproxy->options &= ~PR_O_HTTP_MODE;
3626 goto out;
3627 }
3628 }
3629 else if (strcmp(args[1], "http-server-close") == 0) {
3630 if (kwm == KWM_STD) {
3631 curproxy->options &= ~PR_O_HTTP_MODE;
3632 curproxy->options |= PR_O_HTTP_SCL;
3633 goto out;
3634 }
3635 else if (kwm == KWM_NO) {
3636 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3637 curproxy->options &= ~PR_O_HTTP_MODE;
3638 goto out;
3639 }
3640 }
3641 else if (strcmp(args[1], "http-keep-alive") == 0) {
3642 if (kwm == KWM_STD) {
3643 curproxy->options &= ~PR_O_HTTP_MODE;
3644 curproxy->options |= PR_O_HTTP_KAL;
3645 goto out;
3646 }
3647 else if (kwm == KWM_NO) {
3648 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3649 curproxy->options &= ~PR_O_HTTP_MODE;
3650 goto out;
3651 }
3652 }
3653 else if (strcmp(args[1], "http-tunnel") == 0) {
3654 if (kwm == KWM_STD) {
3655 curproxy->options &= ~PR_O_HTTP_MODE;
3656 curproxy->options |= PR_O_HTTP_TUN;
3657 goto out;
3658 }
3659 else if (kwm == KWM_NO) {
3660 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3661 curproxy->options &= ~PR_O_HTTP_MODE;
3662 goto out;
3663 }
3664 }
3665
Willy Tarreau3842f002009-06-14 11:39:52 +02003666 if (kwm != KWM_STD) {
3667 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003668 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003671 }
3672
Emeric Brun3a058f32009-06-30 18:26:00 +02003673 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003674 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003676 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003677 if (*(args[2]) != '\0') {
3678 if (!strcmp(args[2], "clf")) {
3679 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003680 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003681 } else {
3682 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003685 }
3686 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003687 if (curproxy->conf.logformat_string != default_http_log_format &&
3688 curproxy->conf.logformat_string != default_tcp_log_format &&
3689 curproxy->conf.logformat_string != clf_http_log_format)
3690 free(curproxy->conf.logformat_string);
3691 curproxy->conf.logformat_string = logformat;
3692
3693 free(curproxy->conf.lfs_file);
3694 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3695 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003696 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003697 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003699 if (curproxy->conf.logformat_string != default_http_log_format &&
3700 curproxy->conf.logformat_string != default_tcp_log_format &&
3701 curproxy->conf.logformat_string != clf_http_log_format)
3702 free(curproxy->conf.logformat_string);
3703 curproxy->conf.logformat_string = default_tcp_log_format;
3704
3705 free(curproxy->conf.lfs_file);
3706 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3707 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 else if (!strcmp(args[1], "tcpka")) {
3710 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003713
3714 if (curproxy->cap & PR_CAP_FE)
3715 curproxy->options |= PR_O_TCP_CLI_KA;
3716 if (curproxy->cap & PR_CAP_BE)
3717 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
3719 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
3722
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003724 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003725 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003726 curproxy->options2 &= ~PR_O2_CHK_ANY;
3727 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 if (!*args[2]) { /* no argument */
3729 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3730 curproxy->check_len = strlen(DEF_CHECK_REQ);
3731 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003732 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003733 curproxy->check_req = (char *)malloc(reqlen);
3734 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003735 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003737 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 if (*args[4])
3739 reqlen += strlen(args[4]);
3740 else
3741 reqlen += strlen("HTTP/1.0");
3742
3743 curproxy->check_req = (char *)malloc(reqlen);
3744 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003745 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003747 }
3748 else if (!strcmp(args[1], "ssl-hello-chk")) {
3749 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003752
Willy Tarreaua534fea2008-08-03 12:19:50 +02003753 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003755 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003756 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 }
Willy Tarreau23677902007-05-08 23:50:35 +02003758 else if (!strcmp(args[1], "smtpchk")) {
3759 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003760 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003761 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003762 curproxy->options2 &= ~PR_O2_CHK_ANY;
3763 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003764
3765 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3766 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3767 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3768 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3769 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3770 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3771 curproxy->check_req = (char *)malloc(reqlen);
3772 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3773 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3774 } else {
3775 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3776 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3777 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3778 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3779 }
3780 }
3781 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003782 else if (!strcmp(args[1], "pgsql-check")) {
3783 /* use PostgreSQL request to check servers' health */
3784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3785 err_code |= ERR_WARN;
3786
3787 free(curproxy->check_req);
3788 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003789 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003790 curproxy->options2 |= PR_O2_PGSQL_CHK;
3791
3792 if (*(args[2])) {
3793 int cur_arg = 2;
3794
3795 while (*(args[cur_arg])) {
3796 if (strcmp(args[cur_arg], "user") == 0) {
3797 char * packet;
3798 uint32_t packet_len;
3799 uint32_t pv;
3800
3801 /* suboption header - needs additional argument for it */
3802 if (*(args[cur_arg+1]) == 0) {
3803 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3804 file, linenum, args[0], args[1], args[cur_arg]);
3805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
3807 }
3808
3809 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3810 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3811 pv = htonl(0x30000); /* protocol version 3.0 */
3812
3813 packet = (char*) calloc(1, packet_len);
3814
3815 memcpy(packet + 4, &pv, 4);
3816
3817 /* copy "user" */
3818 memcpy(packet + 8, "user", 4);
3819
3820 /* copy username */
3821 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3822
3823 free(curproxy->check_req);
3824 curproxy->check_req = packet;
3825 curproxy->check_len = packet_len;
3826
3827 packet_len = htonl(packet_len);
3828 memcpy(packet, &packet_len, 4);
3829 cur_arg += 2;
3830 } else {
3831 /* unknown suboption - catchall */
3832 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3833 file, linenum, args[0], args[1]);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 } /* end while loop */
3838 }
3839 }
3840
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003841 else if (!strcmp(args[1], "redis-check")) {
3842 /* use REDIS PING request to check servers' health */
3843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3844 err_code |= ERR_WARN;
3845
3846 free(curproxy->check_req);
3847 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003848 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003849 curproxy->options2 |= PR_O2_REDIS_CHK;
3850
3851 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3852 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3853 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3854 }
3855
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003856 else if (!strcmp(args[1], "mysql-check")) {
3857 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3859 err_code |= ERR_WARN;
3860
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003861 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003862 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003863 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003864 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003865
3866 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3867 * const char mysql40_client_auth_pkt[] = {
3868 * "\x0e\x00\x00" // packet length
3869 * "\x01" // packet number
3870 * "\x00\x00" // client capabilities
3871 * "\x00\x00\x01" // max packet
3872 * "haproxy\x00" // username (null terminated string)
3873 * "\x00" // filler (always 0x00)
3874 * "\x01\x00\x00" // packet length
3875 * "\x00" // packet number
3876 * "\x01" // COM_QUIT command
3877 * };
3878 */
3879
3880 if (*(args[2])) {
3881 int cur_arg = 2;
3882
3883 while (*(args[cur_arg])) {
3884 if (strcmp(args[cur_arg], "user") == 0) {
3885 char *mysqluser;
3886 int packetlen, reqlen, userlen;
3887
3888 /* suboption header - needs additional argument for it */
3889 if (*(args[cur_arg+1]) == 0) {
3890 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3891 file, linenum, args[0], args[1], args[cur_arg]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895 mysqluser = args[cur_arg + 1];
3896 userlen = strlen(mysqluser);
3897 packetlen = userlen + 7;
3898 reqlen = packetlen + 9;
3899
3900 free(curproxy->check_req);
3901 curproxy->check_req = (char *)calloc(1, reqlen);
3902 curproxy->check_len = reqlen;
3903
3904 snprintf(curproxy->check_req, 4, "%c%c%c",
3905 ((unsigned char) packetlen & 0xff),
3906 ((unsigned char) (packetlen >> 8) & 0xff),
3907 ((unsigned char) (packetlen >> 16) & 0xff));
3908
3909 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003910 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003911 curproxy->check_req[8] = 1;
3912 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3913 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3914 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3915 cur_arg += 2;
3916 } else {
3917 /* unknown suboption - catchall */
3918 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3919 file, linenum, args[0], args[1]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923 } /* end while loop */
3924 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003925 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003926 else if (!strcmp(args[1], "ldap-check")) {
3927 /* use LDAP request to check servers' health */
3928 free(curproxy->check_req);
3929 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003930 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003931 curproxy->options2 |= PR_O2_LDAP_CHK;
3932
3933 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3934 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3935 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3936 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003937 else if (!strcmp(args[1], "tcp-check")) {
3938 /* use raw TCPCHK send/expect to check servers' health */
3939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3940 err_code |= ERR_WARN;
3941
3942 free(curproxy->check_req);
3943 curproxy->check_req = NULL;
3944 curproxy->options2 &= ~PR_O2_CHK_ANY;
3945 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3946 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003947 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003948 int cur_arg;
3949
3950 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3951 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003952 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003953
Willy Tarreau87cf5142011-08-19 22:57:24 +02003954 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003955
3956 free(curproxy->fwdfor_hdr_name);
3957 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3958 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3959
3960 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3961 cur_arg = 2;
3962 while (*(args[cur_arg])) {
3963 if (!strcmp(args[cur_arg], "except")) {
3964 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003965 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003966 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3967 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003970 }
3971 /* flush useless bits */
3972 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003973 cur_arg += 2;
3974 } else if (!strcmp(args[cur_arg], "header")) {
3975 /* suboption header - needs additional argument for it */
3976 if (*(args[cur_arg+1]) == 0) {
3977 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3978 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003981 }
3982 free(curproxy->fwdfor_hdr_name);
3983 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3984 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3985 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003986 } else if (!strcmp(args[cur_arg], "if-none")) {
3987 curproxy->options &= ~PR_O_FF_ALWAYS;
3988 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003989 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003990 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003991 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003992 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003995 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003996 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003997 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003998 else if (!strcmp(args[1], "originalto")) {
3999 int cur_arg;
4000
4001 /* insert x-original-to field, but not for the IP address listed as an except.
4002 * set default options (ie: bitfield, header name, etc)
4003 */
4004
4005 curproxy->options |= PR_O_ORGTO;
4006
4007 free(curproxy->orgto_hdr_name);
4008 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4009 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4010
Willy Tarreau87cf5142011-08-19 22:57:24 +02004011 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004012 cur_arg = 2;
4013 while (*(args[cur_arg])) {
4014 if (!strcmp(args[cur_arg], "except")) {
4015 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004016 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 +02004017 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4018 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004021 }
4022 /* flush useless bits */
4023 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4024 cur_arg += 2;
4025 } else if (!strcmp(args[cur_arg], "header")) {
4026 /* suboption header - needs additional argument for it */
4027 if (*(args[cur_arg+1]) == 0) {
4028 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4029 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004032 }
4033 free(curproxy->orgto_hdr_name);
4034 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4035 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4036 cur_arg += 2;
4037 } else {
4038 /* unknown suboption - catchall */
4039 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4040 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004043 }
4044 } /* end while loop */
4045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 else {
4047 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 }
Willy Tarreau93893792009-07-23 13:19:11 +02004051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004053 else if (!strcmp(args[0], "default_backend")) {
4054 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004056
4057 if (*(args[1]) == 0) {
4058 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004061 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004062 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004063 curproxy->defbe.name = strdup(args[1]);
4064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004068
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004069 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4070 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 +01004071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 /* enable reconnections to dispatch */
4074 curproxy->options |= PR_O_REDISP;
4075 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004076 else if (!strcmp(args[0], "http-check")) {
4077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004079
4080 if (strcmp(args[1], "disable-on-404") == 0) {
4081 /* enable a graceful server shutdown on an HTTP 404 response */
4082 curproxy->options |= PR_O_DISABLE404;
4083 }
Willy Tarreauef781042010-01-27 11:53:01 +01004084 else if (strcmp(args[1], "send-state") == 0) {
4085 /* enable emission of the apparent state of a server in HTTP checks */
4086 curproxy->options2 |= PR_O2_CHK_SNDST;
4087 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004088 else if (strcmp(args[1], "expect") == 0) {
4089 const char *ptr_arg;
4090 int cur_arg;
4091
4092 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4093 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097
4098 cur_arg = 2;
4099 /* consider exclamation marks, sole or at the beginning of a word */
4100 while (*(ptr_arg = args[cur_arg])) {
4101 while (*ptr_arg == '!') {
4102 curproxy->options2 ^= PR_O2_EXP_INV;
4103 ptr_arg++;
4104 }
4105 if (*ptr_arg)
4106 break;
4107 cur_arg++;
4108 }
4109 /* now ptr_arg points to the beginning of a word past any possible
4110 * exclamation mark, and cur_arg is the argument which holds this word.
4111 */
4112 if (strcmp(ptr_arg, "status") == 0) {
4113 if (!*(args[cur_arg + 1])) {
4114 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4115 file, linenum, args[0], args[1], ptr_arg);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004120 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004121 curproxy->expect_str = strdup(args[cur_arg + 1]);
4122 }
4123 else if (strcmp(ptr_arg, "string") == 0) {
4124 if (!*(args[cur_arg + 1])) {
4125 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4126 file, linenum, args[0], args[1], ptr_arg);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004131 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004132 curproxy->expect_str = strdup(args[cur_arg + 1]);
4133 }
4134 else if (strcmp(ptr_arg, "rstatus") == 0) {
4135 if (!*(args[cur_arg + 1])) {
4136 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4137 file, linenum, args[0], args[1], ptr_arg);
4138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004142 free(curproxy->expect_str);
4143 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4144 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004145 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4146 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4147 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4148 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
4152 }
4153 else if (strcmp(ptr_arg, "rstring") == 0) {
4154 if (!*(args[cur_arg + 1])) {
4155 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4156 file, linenum, args[0], args[1], ptr_arg);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
4160 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004161 free(curproxy->expect_str);
4162 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4163 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004164 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4165 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4166 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4167 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171 }
4172 else {
4173 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4174 file, linenum, args[0], args[1], ptr_arg);
4175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
4177 }
4178 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004179 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004180 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 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004183 }
4184 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004185 else if (!strcmp(args[0], "tcp-check")) {
4186 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4187 err_code |= ERR_WARN;
4188
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004189 if (strcmp(args[1], "connect") == 0) {
4190 const char *ptr_arg;
4191 int cur_arg;
4192 struct tcpcheck_rule *tcpcheck;
4193 struct list *l;
4194
4195 /* check if first rule is also a 'connect' action */
4196 l = (struct list *)&curproxy->tcpcheck_rules;
4197 if (l->p != l->n) {
4198 tcpcheck = (struct tcpcheck_rule *)l->n;
4199 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4200 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4201 file, linenum);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205 }
4206
4207 cur_arg = 2;
4208 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4209 tcpcheck->action = TCPCHK_ACT_CONNECT;
4210
4211 /* parsing each parameters to fill up the rule */
4212 while (*(ptr_arg = args[cur_arg])) {
4213 /* tcp port */
4214 if (strcmp(args[cur_arg], "port") == 0) {
4215 if ( (atol(args[cur_arg + 1]) > 65535) ||
4216 (atol(args[cur_arg + 1]) < 1) ){
4217 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4218 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
4222 tcpcheck->port = atol(args[cur_arg + 1]);
4223 cur_arg += 2;
4224 }
4225 /* send proxy protocol */
4226 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4227 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4228 cur_arg++;
4229 }
4230#ifdef USE_OPENSSL
4231 else if (strcmp(args[cur_arg], "ssl") == 0) {
4232 curproxy->options |= PR_O_TCPCHK_SSL;
4233 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4234 cur_arg++;
4235 }
4236#endif /* USE_OPENSSL */
4237 else {
4238#ifdef USE_OPENSSL
4239 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4240#else /* USE_OPENSSL */
4241 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4242#endif /* USE_OPENSSL */
4243 file, linenum, args[0], args[1], args[cur_arg]);
4244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
4246 }
4247
4248 }
4249
4250 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4251 }
4252 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004253 if (! *(args[2]) ) {
4254 /* SEND string expected */
4255 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4256 file, linenum, args[0], args[1], args[2]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 } else {
4260 struct tcpcheck_rule *tcpcheck;
4261
4262 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4263
4264 tcpcheck->action = TCPCHK_ACT_SEND;
4265 tcpcheck->string_len = strlen(args[2]);
4266 tcpcheck->string = strdup(args[2]);
4267 tcpcheck->expect_regex = NULL;
4268
4269 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4270 }
4271 }
4272 else if (strcmp(args[1], "send-binary") == 0) {
4273 if (! *(args[2]) ) {
4274 /* SEND binary string expected */
4275 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4276 file, linenum, args[0], args[1], args[2]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 } else {
4280 struct tcpcheck_rule *tcpcheck;
4281 char *err = NULL;
4282
4283 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4284
4285 tcpcheck->action = TCPCHK_ACT_SEND;
4286 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4287 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4288 file, linenum, args[0], args[1], args[2], err);
4289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
4291 }
4292 tcpcheck->expect_regex = NULL;
4293
4294 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4295 }
4296 }
4297 else if (strcmp(args[1], "expect") == 0) {
4298 const char *ptr_arg;
4299 int cur_arg;
4300 int inverse = 0;
4301
4302 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4303 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307
4308 cur_arg = 2;
4309 /* consider exclamation marks, sole or at the beginning of a word */
4310 while (*(ptr_arg = args[cur_arg])) {
4311 while (*ptr_arg == '!') {
4312 inverse = !inverse;
4313 ptr_arg++;
4314 }
4315 if (*ptr_arg)
4316 break;
4317 cur_arg++;
4318 }
4319 /* now ptr_arg points to the beginning of a word past any possible
4320 * exclamation mark, and cur_arg is the argument which holds this word.
4321 */
4322 if (strcmp(ptr_arg, "binary") == 0) {
4323 if (!*(args[cur_arg + 1])) {
4324 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4325 file, linenum, args[0], args[1], ptr_arg);
4326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
4328 }
4329 struct tcpcheck_rule *tcpcheck;
4330 char *err = NULL;
4331
4332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4333
4334 tcpcheck->action = TCPCHK_ACT_EXPECT;
4335 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4336 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4337 file, linenum, args[0], args[1], args[2], err);
4338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
4340 }
4341 tcpcheck->expect_regex = NULL;
4342 tcpcheck->inverse = inverse;
4343
4344 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4345 }
4346 else if (strcmp(ptr_arg, "string") == 0) {
4347 if (!*(args[cur_arg + 1])) {
4348 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4349 file, linenum, args[0], args[1], ptr_arg);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353 struct tcpcheck_rule *tcpcheck;
4354
4355 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4356
4357 tcpcheck->action = TCPCHK_ACT_EXPECT;
4358 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4359 tcpcheck->string = strdup(args[cur_arg + 1]);
4360 tcpcheck->expect_regex = NULL;
4361 tcpcheck->inverse = inverse;
4362
4363 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4364 }
4365 else if (strcmp(ptr_arg, "rstring") == 0) {
4366 if (!*(args[cur_arg + 1])) {
4367 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4368 file, linenum, args[0], args[1], ptr_arg);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
4372 struct tcpcheck_rule *tcpcheck;
4373
4374 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4375
4376 tcpcheck->action = TCPCHK_ACT_EXPECT;
4377 tcpcheck->string_len = 0;
4378 tcpcheck->string = NULL;
4379 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4380 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4381 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4382 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
4386 tcpcheck->inverse = inverse;
4387
4388 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4389 }
4390 else {
4391 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4392 file, linenum, args[0], args[1], ptr_arg);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395 }
4396 }
4397 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004398 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
4402 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004403 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004404 if (curproxy == &defproxy) {
4405 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004408 }
4409
Willy Tarreaub80c2302007-11-30 20:51:32 +01004410 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004412
4413 if (strcmp(args[1], "fail") == 0) {
4414 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004415 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004416 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4417 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004420 }
4421
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004422 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4423 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4424 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004427 }
4428 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4429 }
4430 else {
4431 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004434 }
4435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436#ifdef TPROXY
4437 else if (!strcmp(args[0], "transparent")) {
4438 /* enable transparent proxy connections */
4439 curproxy->options |= PR_O_TRANSP;
4440 }
4441#endif
4442 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004443 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004445
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 if (*(args[1]) == 0) {
4447 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 }
4451 curproxy->maxconn = atol(args[1]);
4452 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004453 else if (!strcmp(args[0], "backlog")) { /* backlog */
4454 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004456
4457 if (*(args[1]) == 0) {
4458 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004461 }
4462 curproxy->backlog = atol(args[1]);
4463 }
Willy Tarreau86034312006-12-29 00:10:33 +01004464 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004467
Willy Tarreau86034312006-12-29 00:10:33 +01004468 if (*(args[1]) == 0) {
4469 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004472 }
4473 curproxy->fullconn = atol(args[1]);
4474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4476 if (*(args[1]) == 0) {
4477 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004481 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4482 if (err) {
4483 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4484 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004487 }
4488 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
4490 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004491 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004492 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004493 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004494
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 if (curproxy == &defproxy) {
4496 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_ALERT | ERR_FATAL;
4498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004500 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004501 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004502
Willy Tarreau902636f2013-03-10 19:44:48 +01004503 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004504 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004505 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004507 goto out;
4508 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004509
4510 proto = protocol_by_family(sk->ss_family);
4511 if (!proto || !proto->connect) {
4512 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4513 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
4516 }
4517
4518 if (port1 != port2) {
4519 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4520 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004524
4525 if (!port1) {
4526 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4527 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
4530 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004531
Willy Tarreaud5191e72010-02-09 20:50:45 +01004532 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004533 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
4535 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004536 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004538
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004539 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4540 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004545 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004546 /**
4547 * The syntax for hash-type config element is
4548 * hash-type {map-based|consistent} [[<algo>] avalanche]
4549 *
4550 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4551 */
4552 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004553
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004554 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4555 err_code |= ERR_WARN;
4556
4557 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004558 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4559 }
4560 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004561 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4562 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004563 else if (strcmp(args[1], "avalanche") == 0) {
4564 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]);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004567 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004568 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004569 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
4572 }
Bhaskar98634f02013-10-29 23:30:51 -04004573
4574 /* set the hash function to use */
4575 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004576 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004577 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004578
4579 /* if consistent with no argument, then avalanche modifier is also applied */
4580 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4581 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004582 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004583 /* set the hash function */
4584 if (!strcmp(args[2], "sdbm")) {
4585 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4586 }
4587 else if (!strcmp(args[2], "djb2")) {
4588 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004589 } else if (!strcmp(args[2], "wt6")) {
4590 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004591 }
4592 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004593 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 -05004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
4596 }
4597
4598 /* set the hash modifier */
4599 if (!strcmp(args[3], "avalanche")) {
4600 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4601 }
4602 else if (*args[3]) {
4603 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004607 }
William Lallemanda73203e2012-03-12 12:48:57 +01004608 }
William Lallemanda73203e2012-03-12 12:48:57 +01004609 else if (strcmp(args[0], "unique-id-format") == 0) {
4610 if (!*(args[1])) {
4611 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
William Lallemand3203ff42012-11-11 17:30:56 +01004615 if (*(args[2])) {
4616 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
4619 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004620 free(curproxy->conf.uniqueid_format_string);
4621 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004622
Willy Tarreau62a61232013-04-12 18:13:46 +02004623 free(curproxy->conf.uif_file);
4624 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4625 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004626 }
William Lallemanda73203e2012-03-12 12:48:57 +01004627
4628 else if (strcmp(args[0], "unique-id-header") == 0) {
4629 if (!*(args[1])) {
4630 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633 }
4634 free(curproxy->header_unique_id);
4635 curproxy->header_unique_id = strdup(args[1]);
4636 }
4637
William Lallemand723b73a2012-02-08 16:37:49 +01004638 else if (strcmp(args[0], "log-format") == 0) {
4639 if (!*(args[1])) {
4640 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
William Lallemand3203ff42012-11-11 17:30:56 +01004644 if (*(args[2])) {
4645 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004649
Willy Tarreau62a61232013-04-12 18:13:46 +02004650 if (curproxy->conf.logformat_string != default_http_log_format &&
4651 curproxy->conf.logformat_string != default_tcp_log_format &&
4652 curproxy->conf.logformat_string != clf_http_log_format)
4653 free(curproxy->conf.logformat_string);
4654 curproxy->conf.logformat_string = strdup(args[1]);
4655
4656 free(curproxy->conf.lfs_file);
4657 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4658 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004659
4660 /* get a chance to improve log-format error reporting by
4661 * reporting the correct line-number when possible.
4662 */
4663 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4664 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4665 file, linenum, curproxy->id);
4666 err_code |= ERR_WARN;
4667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
William Lallemand723b73a2012-02-08 16:37:49 +01004669
William Lallemand0f99e342011-10-12 17:50:54 +02004670 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4671 /* delete previous herited or defined syslog servers */
4672 struct logsrv *back;
4673
4674 if (*(args[1]) != 0) {
4675 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4676 err_code |= ERR_ALERT | ERR_FATAL;
4677 goto out;
4678 }
4679
William Lallemand723b73a2012-02-08 16:37:49 +01004680 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4681 LIST_DEL(&tmplogsrv->list);
4682 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004683 }
4684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004686 struct logsrv *logsrv;
4687
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004689 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004690 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004691 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004692 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004693 LIST_INIT(&node->list);
4694 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 }
4697 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004698 struct sockaddr_storage *sk;
4699 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004700
4701 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702
William Lallemand0f99e342011-10-12 17:50:54 +02004703 logsrv->facility = get_log_facility(args[2]);
4704 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 }
4710
William Lallemand0f99e342011-10-12 17:50:54 +02004711 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->level = get_log_level(args[3]);
4714 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 }
4720 }
4721
William Lallemand0f99e342011-10-12 17:50:54 +02004722 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004723 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004724 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004725 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004726 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004730 }
4731 }
4732
Willy Tarreau902636f2013-03-10 19:44:48 +01004733 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004734 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004735 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004736 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004737 goto out;
4738 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004739
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004740 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004741
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004742 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743 if (port1 != port2) {
4744 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4745 file, linenum, args[0], args[1]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
4749
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004750 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004751 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
William Lallemand0f99e342011-10-12 17:50:54 +02004753
4754 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
4756 else {
4757 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4758 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
4762 }
4763 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004764 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004765 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004766 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004767 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004768
Willy Tarreau977b8e42006-12-29 14:19:17 +01004769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004771
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004773 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4774 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004778
4779 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004780 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4781 free(curproxy->conn_src.iface_name);
4782 curproxy->conn_src.iface_name = NULL;
4783 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004784
Willy Tarreau902636f2013-03-10 19:44:48 +01004785 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004786 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004787 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004788 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004789 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004790 goto out;
4791 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004792
4793 proto = protocol_by_family(sk->ss_family);
4794 if (!proto || !proto->connect) {
4795 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004796 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004800
4801 if (port1 != port2) {
4802 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4803 file, linenum, args[0], args[1]);
4804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
4806 }
4807
Willy Tarreauef9a3602012-12-08 22:29:20 +01004808 curproxy->conn_src.source_addr = *sk;
4809 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004810
4811 cur_arg = 2;
4812 while (*(args[cur_arg])) {
4813 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004814#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4815#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004816 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004817 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4818 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004821 }
4822#endif
4823 if (!*args[cur_arg + 1]) {
4824 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4825 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828 }
4829
4830 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004831 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4832 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004833 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004834 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4835 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004836 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4837 char *name, *end;
4838
4839 name = args[cur_arg+1] + 7;
4840 while (isspace(*name))
4841 name++;
4842
4843 end = name;
4844 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4845 end++;
4846
Willy Tarreauef9a3602012-12-08 22:29:20 +01004847 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4848 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4849 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4850 curproxy->conn_src.bind_hdr_len = end - name;
4851 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4852 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4853 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004854
4855 /* now look for an occurrence number */
4856 while (isspace(*end))
4857 end++;
4858 if (*end == ',') {
4859 end++;
4860 name = end;
4861 if (*end == '-')
4862 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004863 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004864 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004865 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004866 }
4867
Willy Tarreauef9a3602012-12-08 22:29:20 +01004868 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004869 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4870 " occurrences values smaller than %d.\n",
4871 file, linenum, MAX_HDR_HISTORY);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004876 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004877
Willy Tarreau902636f2013-03-10 19:44:48 +01004878 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004879 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004880 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004881 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004882 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004883 goto out;
4884 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004885
4886 proto = protocol_by_family(sk->ss_family);
4887 if (!proto || !proto->connect) {
4888 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4889 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004893
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004894 if (port1 != port2) {
4895 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4896 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
4899 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004900 curproxy->conn_src.tproxy_addr = *sk;
4901 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902 }
4903 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004904#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004905 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004906#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004907#else /* no TPROXY support */
4908 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004909 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004912#endif
4913 cur_arg += 2;
4914 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004915 }
4916
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004917 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4918#ifdef SO_BINDTODEVICE
4919 if (!*args[cur_arg + 1]) {
4920 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004925 free(curproxy->conn_src.iface_name);
4926 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4927 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004928 global.last_checks |= LSTCHK_NETADM;
4929#else
4930 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4931 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_ALERT | ERR_FATAL;
4933 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004934#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004935 cur_arg += 2;
4936 continue;
4937 }
4938 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004939 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004944 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4945 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4946 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957
4958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004959 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004960 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
4964 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004966 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 }
4971 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004973 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 }
4978 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004980 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 }
4985 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004987 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004988 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004992 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004994 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004995 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004997 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004998 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004999 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005001 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005002 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005004 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005005
5006 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5007 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 +01005008 }
5009 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005015
5016 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5017 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 +01005018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026
5027 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005028 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005029 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005030 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
5033 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005035 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005036 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005037 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 }
5040 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005042 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005043 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
5047 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005049 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005056 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005057 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005061 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005063 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005064 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005066 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005069 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005070
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 if (curproxy == &defproxy) {
5072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005076 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 if (*(args[1]) == 0) {
5080 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005084
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005085 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005086 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5087 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5088 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
5091 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005092 err_code |= warnif_cond_conflicts(cond,
5093 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5094 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005095 }
5096 else if (*args[2]) {
5097 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5098 file, linenum, args[0], args[2]);
5099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
5102
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005103 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005104 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005105 wl->s = strdup(args[1]);
5106 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005107 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
5109 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005116
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005118 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005119 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005125 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005126 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005133 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
5144
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005147 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "rspidel")) { /* delete response header 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_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005154 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
5158 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005161 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
5165 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005166 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005167
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 if (curproxy == &defproxy) {
5169 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 if (*(args[1]) == 0) {
5177 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005182 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005183 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5184 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5185 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005189 err_code |= warnif_cond_conflicts(cond,
5190 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5191 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005192 }
5193 else if (*args[2]) {
5194 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5195 file, linenum, args[0], args[2]);
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
5198 }
5199
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005200 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005201 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005202 wl->s = strdup(args[1]);
5203 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
5205 else if (!strcmp(args[0], "errorloc") ||
5206 !strcmp(args[0], "errorloc302") ||
5207 !strcmp(args[0], "errorloc303")) { /* error location */
5208 int errnum, errlen;
5209 char *err;
5210
Willy Tarreau977b8e42006-12-29 14:19:17 +01005211 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005213
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005215 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219
5220 errnum = atol(args[1]);
5221 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005222 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5223 err = malloc(errlen);
5224 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005226 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5227 err = malloc(errlen);
5228 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
5230
Willy Tarreau0f772532006-12-23 20:51:41 +01005231 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5232 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005233 chunk_destroy(&curproxy->errmsg[rc]);
5234 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005235 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005238
5239 if (rc >= HTTP_ERR_SIZE) {
5240 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5241 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 free(err);
5243 }
5244 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005245 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5246 int errnum, errlen, fd;
5247 char *err;
5248 struct stat stat;
5249
5250 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252
5253 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005254 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005257 }
5258
5259 fd = open(args[2], O_RDONLY);
5260 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5261 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5262 file, linenum, args[2], args[1]);
5263 if (fd >= 0)
5264 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005267 }
5268
Willy Tarreau27a674e2009-08-17 07:23:33 +02005269 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005270 errlen = stat.st_size;
5271 } else {
5272 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005273 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005274 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005275 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005276 }
5277
5278 err = malloc(errlen); /* malloc() must succeed during parsing */
5279 errnum = read(fd, err, errlen);
5280 if (errnum != errlen) {
5281 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5282 file, linenum, args[2], args[1]);
5283 close(fd);
5284 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005287 }
5288 close(fd);
5289
5290 errnum = atol(args[1]);
5291 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5292 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005293 chunk_destroy(&curproxy->errmsg[rc]);
5294 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005295 break;
5296 }
5297 }
5298
5299 if (rc >= HTTP_ERR_SIZE) {
5300 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5301 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005302 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005303 free(err);
5304 }
5305 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005306 else if (!strcmp(args[0], "compression")) {
5307 struct comp *comp;
5308 if (curproxy->comp == NULL) {
5309 comp = calloc(1, sizeof(struct comp));
5310 curproxy->comp = comp;
5311 } else {
5312 comp = curproxy->comp;
5313 }
5314
5315 if (!strcmp(args[1], "algo")) {
5316 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005317 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005318
William Lallemand82fe75c2012-10-23 10:25:10 +02005319 cur_arg = 2;
5320 if (!*args[cur_arg]) {
5321 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5322 file, linenum, args[0]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326 while (*(args[cur_arg])) {
5327 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5328 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5329 file, linenum, args[0], args[cur_arg]);
5330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
5332 }
William Lallemand552df672012-11-07 13:21:47 +01005333 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5334 curproxy->comp->algos->end(&ctx);
5335 } else {
5336 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5337 file, linenum, args[0], args[cur_arg]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005341 cur_arg ++;
5342 continue;
5343 }
5344 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005345 else if (!strcmp(args[1], "offload")) {
5346 comp->offload = 1;
5347 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005348 else if (!strcmp(args[1], "type")) {
5349 int cur_arg;
5350 cur_arg = 2;
5351 if (!*args[cur_arg]) {
5352 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5353 file, linenum, args[0]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357 while (*(args[cur_arg])) {
5358 comp_append_type(comp, args[cur_arg]);
5359 cur_arg ++;
5360 continue;
5361 }
5362 }
5363 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005364 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005365 file, linenum, args[0]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005371 struct cfg_kw_list *kwl;
5372 int index;
5373
5374 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5375 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5376 if (kwl->kw[index].section != CFG_LISTEN)
5377 continue;
5378 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5379 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005380 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005381 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005382 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005385 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005386 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005387 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005388 err_code |= ERR_WARN;
5389 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005390 }
Willy Tarreau93893792009-07-23 13:19:11 +02005391 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005392 }
5393 }
5394 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005395
Willy Tarreau6daf3432008-01-22 16:44:08 +01005396 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 }
Willy Tarreau93893792009-07-23 13:19:11 +02005400 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005401 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005402 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403}
5404
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005405int
5406cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5407{
5408
5409 int err_code = 0;
5410 const char *err;
5411
5412 if (!strcmp(args[0], "userlist")) { /* new userlist */
5413 struct userlist *newul;
5414
5415 if (!*args[1]) {
5416 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5417 file, linenum, args[0]);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421
5422 err = invalid_char(args[1]);
5423 if (err) {
5424 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5425 file, linenum, *err, args[0], args[1]);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
5429
5430 for (newul = userlist; newul; newul = newul->next)
5431 if (!strcmp(newul->name, args[1])) {
5432 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5433 file, linenum, args[1]);
5434 err_code |= ERR_WARN;
5435 goto out;
5436 }
5437
5438 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5439 if (!newul) {
5440 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5441 err_code |= ERR_ALERT | ERR_ABORT;
5442 goto out;
5443 }
5444
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005445 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005446 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005447 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5448 err_code |= ERR_ALERT | ERR_ABORT;
5449 goto out;
5450 }
5451
5452 newul->next = userlist;
5453 userlist = newul;
5454
5455 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005456 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005457 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005458 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005459
5460 if (!*args[1]) {
5461 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5462 file, linenum, args[0]);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
5466
5467 err = invalid_char(args[1]);
5468 if (err) {
5469 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5470 file, linenum, *err, args[0], args[1]);
5471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
5474
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005475 for (ag = userlist->groups; ag; ag = ag->next)
5476 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005477 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5478 file, linenum, args[1], userlist->name);
5479 err_code |= ERR_ALERT;
5480 goto out;
5481 }
5482
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005483 ag = calloc(1, sizeof(*ag));
5484 if (!ag) {
5485 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5486 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005487 goto out;
5488 }
5489
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005490 ag->name = strdup(args[1]);
5491 if (!ag) {
5492 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5493 err_code |= ERR_ALERT | ERR_ABORT;
5494 goto out;
5495 }
5496
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005497 cur_arg = 2;
5498
5499 while (*args[cur_arg]) {
5500 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005501 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005502 cur_arg += 2;
5503 continue;
5504 } else {
5505 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5506 file, linenum, args[0]);
5507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
5509 }
5510 }
5511
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005512 ag->next = userlist->groups;
5513 userlist->groups = ag;
5514
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005515 } else if (!strcmp(args[0], "user")) { /* new user */
5516 struct auth_users *newuser;
5517 int cur_arg;
5518
5519 if (!*args[1]) {
5520 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5521 file, linenum, args[0]);
5522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
5524 }
5525
5526 for (newuser = userlist->users; newuser; newuser = newuser->next)
5527 if (!strcmp(newuser->user, args[1])) {
5528 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5529 file, linenum, args[1], userlist->name);
5530 err_code |= ERR_ALERT;
5531 goto out;
5532 }
5533
5534 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5535 if (!newuser) {
5536 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5537 err_code |= ERR_ALERT | ERR_ABORT;
5538 goto out;
5539 }
5540
5541 newuser->user = strdup(args[1]);
5542
5543 newuser->next = userlist->users;
5544 userlist->users = newuser;
5545
5546 cur_arg = 2;
5547
5548 while (*args[cur_arg]) {
5549 if (!strcmp(args[cur_arg], "password")) {
5550#ifndef CONFIG_HAP_CRYPT
5551 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5552 file, linenum);
5553 err_code |= ERR_ALERT;
5554#endif
5555 newuser->pass = strdup(args[cur_arg + 1]);
5556 cur_arg += 2;
5557 continue;
5558 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5559 newuser->pass = strdup(args[cur_arg + 1]);
5560 newuser->flags |= AU_O_INSECURE;
5561 cur_arg += 2;
5562 continue;
5563 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005564 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005565 cur_arg += 2;
5566 continue;
5567 } else {
5568 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5569 file, linenum, args[0]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573 }
5574 } else {
5575 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 }
5578
5579out:
5580 return err_code;
5581}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582
5583/*
5584 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005585 * Returns the error code, 0 if OK, or any combination of :
5586 * - ERR_ABORT: must abort ASAP
5587 * - ERR_FATAL: we can continue parsing but not start the service
5588 * - ERR_WARN: a warning has been emitted
5589 * - ERR_ALERT: an alert has been emitted
5590 * Only the two first ones can stop processing, the two others are just
5591 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005593int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005595 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 FILE *f;
5597 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005598 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005599 struct cfg_section *cs = NULL;
5600 struct cfg_section *ics;
5601
5602 /* Register internal sections */
5603 if (!cfg_register_section("listen", cfg_parse_listen) ||
5604 !cfg_register_section("frontend", cfg_parse_listen) ||
5605 !cfg_register_section("backend", cfg_parse_listen) ||
5606 !cfg_register_section("ruleset", cfg_parse_listen) ||
5607 !cfg_register_section("defaults", cfg_parse_listen) ||
5608 !cfg_register_section("global", cfg_parse_global) ||
5609 !cfg_register_section("userlist", cfg_parse_users) ||
5610 !cfg_register_section("peers", cfg_parse_peers))
5611 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 if ((f=fopen(file,"r")) == NULL)
5614 return -1;
5615
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005616 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005617 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005618 char *end;
5619 char *args[MAX_LINE_ARGS + 1];
5620 char *line = thisline;
5621
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 linenum++;
5623
5624 end = line + strlen(line);
5625
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005626 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5627 /* Check if we reached the limit and the last char is not \n.
5628 * Watch out for the last line without the terminating '\n'!
5629 */
5630 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005631 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005633 }
5634
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005636 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 line++;
5638
5639 arg = 0;
5640 args[arg] = line;
5641
5642 while (*line && arg < MAX_LINE_ARGS) {
5643 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5644 * C equivalent value. Other combinations left unchanged (eg: \1).
5645 */
5646 if (*line == '\\') {
5647 int skip = 0;
5648 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5649 *line = line[1];
5650 skip = 1;
5651 }
5652 else if (line[1] == 'r') {
5653 *line = '\r';
5654 skip = 1;
5655 }
5656 else if (line[1] == 'n') {
5657 *line = '\n';
5658 skip = 1;
5659 }
5660 else if (line[1] == 't') {
5661 *line = '\t';
5662 skip = 1;
5663 }
5664 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005665 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 unsigned char hex1, hex2;
5667 hex1 = toupper(line[2]) - '0';
5668 hex2 = toupper(line[3]) - '0';
5669 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5670 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5671 *line = (hex1<<4) + hex2;
5672 skip = 3;
5673 }
5674 else {
5675 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 }
5678 }
5679 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005680 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 end -= skip;
5682 }
5683 line++;
5684 }
5685 else if (*line == '#' || *line == '\n' || *line == '\r') {
5686 /* end of string, end of loop */
5687 *line = 0;
5688 break;
5689 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005690 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005692 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005693 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 line++;
5695 args[++arg] = line;
5696 }
5697 else {
5698 line++;
5699 }
5700 }
5701
5702 /* empty line */
5703 if (!**args)
5704 continue;
5705
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005706 if (*line) {
5707 /* we had to stop due to too many args.
5708 * Let's terminate the string, print the offending part then cut the
5709 * last arg.
5710 */
5711 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5712 line++;
5713 *line = '\0';
5714
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005715 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005716 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 args[arg] = line;
5719 }
5720
Willy Tarreau540abe42007-05-02 20:50:16 +02005721 /* zero out remaining args and ensure that at least one entry
5722 * is zeroed out.
5723 */
5724 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 args[arg] = line;
5726 }
5727
Willy Tarreau3842f002009-06-14 11:39:52 +02005728 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005729 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005730 char *tmp;
5731
Willy Tarreau3842f002009-06-14 11:39:52 +02005732 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005733 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005734 for (arg=0; *args[arg+1]; arg++)
5735 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005736 *tmp = '\0'; // fix the next arg to \0
5737 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005738 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005739 else if (!strcmp(args[0], "default")) {
5740 kwm = KWM_DEF;
5741 for (arg=0; *args[arg+1]; arg++)
5742 args[arg] = args[arg+1]; // shift args after inversion
5743 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005744
William Lallemand0f99e342011-10-12 17:50:54 +02005745 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5746 strcmp(args[0], "log") != 0) {
5747 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005749 }
5750
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005751 /* detect section start */
5752 list_for_each_entry(ics, &sections, list) {
5753 if (strcmp(args[0], ics->section_name) == 0) {
5754 cursection = ics->section_name;
5755 cs = ics;
5756 break;
5757 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005758 }
5759
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005761 if (cs)
5762 err_code |= cs->section_parser(file, linenum, args, kwm);
5763 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005764 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005767
5768 if (err_code & ERR_ABORT)
5769 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005771 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005773 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005774}
5775
Willy Tarreaubb925012009-07-23 13:36:36 +02005776/*
5777 * Returns the error code, 0 if OK, or any combination of :
5778 * - ERR_ABORT: must abort ASAP
5779 * - ERR_FATAL: we can continue parsing but not start the service
5780 * - ERR_WARN: a warning has been emitted
5781 * - ERR_ALERT: an alert has been emitted
5782 * Only the two first ones can stop processing, the two others are just
5783 * indicators.
5784 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005785int check_config_validity()
5786{
5787 int cfgerr = 0;
5788 struct proxy *curproxy = NULL;
5789 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005790 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005791 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005792 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005794 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 /*
5796 * Now, check for the integrity of all that we have collected.
5797 */
5798
5799 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005800 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801
Willy Tarreau193b8c62012-11-22 00:17:38 +01005802 if (!global.tune.max_http_hdr)
5803 global.tune.max_http_hdr = MAX_HTTP_HDR;
5804
5805 if (!global.tune.cookie_len)
5806 global.tune.cookie_len = CAPTURE_LEN;
5807
5808 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5809
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005810 /* Post initialisation of the users and groups lists. */
5811 err_code = userlist_postinit();
5812 if (err_code != ERR_NONE)
5813 goto out;
5814
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005815 /* first, we will invert the proxy list order */
5816 curproxy = NULL;
5817 while (proxy) {
5818 struct proxy *next;
5819
5820 next = proxy->next;
5821 proxy->next = curproxy;
5822 curproxy = proxy;
5823 if (!next)
5824 break;
5825 proxy = next;
5826 }
5827
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005829 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005830 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005831 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005832 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005833 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005834 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005835 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005836
Willy Tarreau050536d2012-10-04 08:47:34 +02005837 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005838 /* proxy ID not set, use automatic numbering with first
5839 * spare entry starting with next_pxid.
5840 */
5841 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5842 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5843 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005844 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005845 next_pxid++;
5846
Willy Tarreau55ea7572007-06-17 19:56:27 +02005847
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005849 /* ensure we don't keep listeners uselessly bound */
5850 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 curproxy = curproxy->next;
5852 continue;
5853 }
5854
Willy Tarreau102df612014-05-07 23:56:38 +02005855 /* Check multi-process mode compatibility for the current proxy */
5856
5857 if (curproxy->bind_proc) {
5858 /* an explicit bind-process was specified, let's check how many
5859 * processes remain.
5860 */
5861 nbproc = popcount(curproxy->bind_proc);
5862
5863 curproxy->bind_proc &= nbits(global.nbproc);
5864 if (!curproxy->bind_proc && nbproc == 1) {
5865 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);
5866 curproxy->bind_proc = 1;
5867 }
5868 else if (!curproxy->bind_proc && nbproc > 1) {
5869 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);
5870 curproxy->bind_proc = 0;
5871 }
5872 }
5873
Willy Tarreau3d209582014-05-09 17:06:11 +02005874 /* check and reduce the bind-proc of each listener */
5875 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
5876 unsigned long mask;
5877
5878 if (!bind_conf->bind_proc)
5879 continue;
5880
5881 mask = nbits(global.nbproc);
5882 if (curproxy->bind_proc)
5883 mask &= curproxy->bind_proc;
5884 /* mask cannot be null here thanks to the previous checks */
5885
5886 nbproc = popcount(bind_conf->bind_proc);
5887 bind_conf->bind_proc &= mask;
5888
5889 if (!bind_conf->bind_proc && nbproc == 1) {
5890 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",
5891 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5892 bind_conf->bind_proc = mask & ~(mask - 1);
5893 }
5894 else if (!bind_conf->bind_proc && nbproc > 1) {
5895 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",
5896 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5897 bind_conf->bind_proc = 0;
5898 }
5899 }
5900
Willy Tarreau102df612014-05-07 23:56:38 +02005901 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
5902 * We now check how many processes the proxy will effectively run on.
5903 */
5904
5905 nbproc = global.nbproc;
5906 if (curproxy->bind_proc)
5907 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
5908
5909 if (global.nbproc > 1 && curproxy->table.peers.name) {
5910 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
5911 curproxy->id);
5912 cfgerr++;
5913 }
Willy Tarreau16a21472012-11-19 12:39:59 +01005914
Willy Tarreauff01a212009-03-15 13:46:16 +01005915 switch (curproxy->mode) {
5916 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005917 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005918 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005919 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5920 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005921 cfgerr++;
5922 }
5923
5924 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005925 Warning("config : servers will be ignored for %s '%s'.\n",
5926 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005927 break;
5928
5929 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005930 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005931 break;
5932
5933 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005934 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005935 break;
5936 }
5937
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005938 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005939 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005940 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005941 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5942 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005943 cfgerr++;
5944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005946 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005947 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5948 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005949 cfgerr++;
5950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005952 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005953 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5954 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005955 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005956 }
5957 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005958 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005959 /* If no LB algo is set in a backend, and we're not in
5960 * transparent mode, dispatch mode nor proxy mode, we
5961 * want to use balance roundrobin by default.
5962 */
5963 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5964 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 }
5966 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005967
Willy Tarreau1620ec32011-08-06 17:05:02 +02005968 if (curproxy->options & PR_O_DISPATCH)
5969 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5970 else if (curproxy->options & PR_O_HTTP_PROXY)
5971 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5972 else if (curproxy->options & PR_O_TRANSP)
5973 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005974
Willy Tarreau1620ec32011-08-06 17:05:02 +02005975 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5976 if (curproxy->options & PR_O_DISABLE404) {
5977 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5978 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5979 err_code |= ERR_WARN;
5980 curproxy->options &= ~PR_O_DISABLE404;
5981 }
5982 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5983 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5984 "send-state", proxy_type_str(curproxy), curproxy->id);
5985 err_code |= ERR_WARN;
5986 curproxy->options &= ~PR_O2_CHK_SNDST;
5987 }
Willy Tarreauef781042010-01-27 11:53:01 +01005988 }
5989
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005990 /* if a default backend was specified, let's find it */
5991 if (curproxy->defbe.name) {
5992 struct proxy *target;
5993
Alex Williams96532db2009-11-01 21:27:13 -05005994 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005995 if (!target) {
5996 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5997 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005998 cfgerr++;
5999 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006000 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6001 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006002 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006003 } else {
6004 free(curproxy->defbe.name);
6005 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006006 /* we force the backend to be present on at least all of
6007 * the frontend's processes.
6008 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006009 if (target->bind_proc)
6010 target->bind_proc = curproxy->bind_proc ?
6011 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006012
6013 /* Emit a warning if this proxy also has some servers */
6014 if (curproxy->srv) {
6015 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6016 curproxy->id);
6017 err_code |= ERR_WARN;
6018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
6020 }
6021
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006022 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006023 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6024 /* map jump target for ACT_SETBE in req_rep chain */
6025 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006026 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006027 struct proxy *target;
6028
Willy Tarreaua496b602006-12-17 23:15:24 +01006029 if (exp->action != ACT_SETBE)
6030 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006031
Alex Williams96532db2009-11-01 21:27:13 -05006032 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006033 if (!target) {
6034 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6035 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006036 cfgerr++;
6037 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006038 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6039 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006040 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006041 } else {
6042 free((void *)exp->replace);
6043 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006044 /* we force the backend to be present on at least all of
6045 * the frontend's processes.
6046 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006047 if (target->bind_proc)
6048 target->bind_proc = curproxy->bind_proc ?
6049 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006050 }
6051 }
6052 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006053
6054 /* find the target proxy for 'use_backend' rules */
6055 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006056 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006057 struct logformat_node *node;
6058 char *pxname;
6059
6060 /* Try to parse the string as a log format expression. If the result
6061 * of the parsing is only one entry containing a simple string, then
6062 * it's a standard string corresponding to a static rule, thus the
6063 * parsing is cancelled and be.name is restored to be resolved.
6064 */
6065 pxname = rule->be.name;
6066 LIST_INIT(&rule->be.expr);
6067 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6068 curproxy->conf.args.file, curproxy->conf.args.line);
6069 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6070
6071 if (!LIST_ISEMPTY(&rule->be.expr)) {
6072 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6073 rule->dynamic = 1;
6074 free(pxname);
6075 continue;
6076 }
6077 /* simple string: free the expression and fall back to static rule */
6078 free(node->arg);
6079 free(node);
6080 }
6081
6082 rule->dynamic = 0;
6083 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006084
Alex Williams96532db2009-11-01 21:27:13 -05006085 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006086
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006087 if (!target) {
6088 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6089 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006090 cfgerr++;
6091 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006092 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6093 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006094 cfgerr++;
6095 } else {
6096 free((void *)rule->be.name);
6097 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006098 /* we force the backend to be present on at least all of
6099 * the frontend's processes.
6100 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006101 if (target->bind_proc)
6102 target->bind_proc = curproxy->bind_proc ?
6103 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006104 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006105 }
6106
6107 /* find the target proxy for 'use_backend' rules */
6108 list_for_each_entry(srule, &curproxy->server_rules, list) {
6109 struct server *target = findserver(curproxy, srule->srv.name);
6110
6111 if (!target) {
6112 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6113 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6114 cfgerr++;
6115 continue;
6116 }
6117 free((void *)srule->srv.name);
6118 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006119 }
6120
Emeric Brunb982a3d2010-01-04 15:45:53 +01006121 /* find the target table for 'stick' rules */
6122 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6123 struct proxy *target;
6124
Emeric Brun1d33b292010-01-04 15:47:17 +01006125 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6126 if (mrule->flags & STK_IS_STORE)
6127 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6128
Emeric Brunb982a3d2010-01-04 15:45:53 +01006129 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006130 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006131 else
6132 target = curproxy;
6133
6134 if (!target) {
6135 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6136 curproxy->id, mrule->table.name);
6137 cfgerr++;
6138 }
6139 else if (target->table.size == 0) {
6140 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6141 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6142 cfgerr++;
6143 }
Willy Tarreau12785782012-04-27 21:37:17 +02006144 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6145 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006146 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6147 cfgerr++;
6148 }
6149 else {
6150 free((void *)mrule->table.name);
6151 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006152 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006153 }
6154 }
6155
6156 /* find the target table for 'store response' rules */
6157 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6158 struct proxy *target;
6159
Emeric Brun1d33b292010-01-04 15:47:17 +01006160 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6161
Emeric Brunb982a3d2010-01-04 15:45:53 +01006162 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006163 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006164 else
6165 target = curproxy;
6166
6167 if (!target) {
6168 Alert("Proxy '%s': unable to find store table '%s'.\n",
6169 curproxy->id, mrule->table.name);
6170 cfgerr++;
6171 }
6172 else if (target->table.size == 0) {
6173 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6174 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6175 cfgerr++;
6176 }
Willy Tarreau12785782012-04-27 21:37:17 +02006177 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6178 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006179 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6180 cfgerr++;
6181 }
6182 else {
6183 free((void *)mrule->table.name);
6184 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006185 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006186 }
6187 }
6188
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006189 /* find the target table for 'tcp-request' layer 4 rules */
6190 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6191 struct proxy *target;
6192
Willy Tarreaub4c84932013-07-23 19:15:30 +02006193 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006194 continue;
6195
6196 if (trule->act_prm.trk_ctr.table.n)
6197 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6198 else
6199 target = curproxy;
6200
6201 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006202 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6203 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006204 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006205 cfgerr++;
6206 }
6207 else if (target->table.size == 0) {
6208 Alert("Proxy '%s': table '%s' used but not configured.\n",
6209 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6210 cfgerr++;
6211 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006212 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6213 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6214 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 +01006215 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006216 cfgerr++;
6217 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006218 else {
6219 free(trule->act_prm.trk_ctr.table.n);
6220 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006221 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006222 * to pass a list of counters to track and allocate them right here using
6223 * stktable_alloc_data_type().
6224 */
6225 }
6226 }
6227
Willy Tarreaud1f96522010-08-03 19:34:32 +02006228 /* find the target table for 'tcp-request' layer 6 rules */
6229 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6230 struct proxy *target;
6231
Willy Tarreaub4c84932013-07-23 19:15:30 +02006232 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006233 continue;
6234
6235 if (trule->act_prm.trk_ctr.table.n)
6236 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6237 else
6238 target = curproxy;
6239
6240 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006241 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6242 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006243 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006244 cfgerr++;
6245 }
6246 else if (target->table.size == 0) {
6247 Alert("Proxy '%s': table '%s' used but not configured.\n",
6248 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6249 cfgerr++;
6250 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006251 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6252 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6253 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 +01006254 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006255 cfgerr++;
6256 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006257 else {
6258 free(trule->act_prm.trk_ctr.table.n);
6259 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006260 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006261 * to pass a list of counters to track and allocate them right here using
6262 * stktable_alloc_data_type().
6263 */
6264 }
6265 }
6266
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006267 /* move any "block" rules at the beginning of the http-request rules */
6268 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6269 /* insert block_rules into http_req_rules at the beginning */
6270 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6271 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6272 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6273 curproxy->http_req_rules.n = curproxy->block_rules.n;
6274 LIST_INIT(&curproxy->block_rules);
6275 }
6276
Emeric Brun32da3c42010-09-23 18:39:19 +02006277 if (curproxy->table.peers.name) {
6278 struct peers *curpeers = peers;
6279
6280 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6281 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6282 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006283 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006284 break;
6285 }
6286 }
6287
6288 if (!curpeers) {
6289 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6290 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006291 free((void *)curproxy->table.peers.name);
6292 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006293 cfgerr++;
6294 }
6295 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006296 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6297 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006298 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006299 cfgerr++;
6300 }
6301 }
6302
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006303 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006304 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006305 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6306 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6307 "proxy", curproxy->id);
6308 cfgerr++;
6309 goto out_uri_auth_compat;
6310 }
6311
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006312 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006313 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006314 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006315 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006316
Willy Tarreau95fa4692010-02-01 13:05:50 +01006317 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6318 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006319
6320 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006321 uri_auth_compat_req[i++] = "realm";
6322 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6323 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006324
Willy Tarreau95fa4692010-02-01 13:05:50 +01006325 uri_auth_compat_req[i++] = "unless";
6326 uri_auth_compat_req[i++] = "{";
6327 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6328 uri_auth_compat_req[i++] = "}";
6329 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006330
Willy Tarreauff011f22011-01-06 17:51:27 +01006331 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6332 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006333 cfgerr++;
6334 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006335 }
6336
Willy Tarreauff011f22011-01-06 17:51:27 +01006337 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006338
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006339 if (curproxy->uri_auth->auth_realm) {
6340 free(curproxy->uri_auth->auth_realm);
6341 curproxy->uri_auth->auth_realm = NULL;
6342 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006343
6344 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006345 }
6346out_uri_auth_compat:
6347
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006348 /* compile the log format */
6349 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006350 if (curproxy->conf.logformat_string != default_http_log_format &&
6351 curproxy->conf.logformat_string != default_tcp_log_format &&
6352 curproxy->conf.logformat_string != clf_http_log_format)
6353 free(curproxy->conf.logformat_string);
6354 curproxy->conf.logformat_string = NULL;
6355 free(curproxy->conf.lfs_file);
6356 curproxy->conf.lfs_file = NULL;
6357 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006358 }
6359
Willy Tarreau62a61232013-04-12 18:13:46 +02006360 if (curproxy->conf.logformat_string) {
6361 curproxy->conf.args.ctx = ARGC_LOG;
6362 curproxy->conf.args.file = curproxy->conf.lfs_file;
6363 curproxy->conf.args.line = curproxy->conf.lfs_line;
6364 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006365 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006366 curproxy->conf.args.file = NULL;
6367 curproxy->conf.args.line = 0;
6368 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006369
Willy Tarreau62a61232013-04-12 18:13:46 +02006370 if (curproxy->conf.uniqueid_format_string) {
6371 curproxy->conf.args.ctx = ARGC_UIF;
6372 curproxy->conf.args.file = curproxy->conf.uif_file;
6373 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006374 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006375 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6376 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006377 curproxy->conf.args.file = NULL;
6378 curproxy->conf.args.line = 0;
6379 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006380
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006381 /* only now we can check if some args remain unresolved.
6382 * This must be done after the users and groups resolution.
6383 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006384 cfgerr += smp_resolve_args(curproxy);
6385 if (!cfgerr)
6386 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006387
Willy Tarreau2738a142006-07-08 17:28:09 +02006388 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006389 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006390 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006391 (!curproxy->timeout.connect ||
6392 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006393 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006394 " | While not properly invalid, you will certainly encounter various problems\n"
6395 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006396 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006397 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006398 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006399 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006400
Willy Tarreau1fa31262007-12-03 00:36:16 +01006401 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6402 * We must still support older configurations, so let's find out whether those
6403 * parameters have been set or must be copied from contimeouts.
6404 */
6405 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006406 if (!curproxy->timeout.tarpit ||
6407 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006408 /* tarpit timeout not set. We search in the following order:
6409 * default.tarpit, curr.connect, default.connect.
6410 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006411 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006412 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006413 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006414 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006415 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006416 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006417 }
6418 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006419 (!curproxy->timeout.queue ||
6420 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006421 /* queue timeout not set. We search in the following order:
6422 * default.queue, curr.connect, default.connect.
6423 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006424 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006425 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006426 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006427 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006428 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006429 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006430 }
6431 }
6432
Willy Tarreau1620ec32011-08-06 17:05:02 +02006433 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006434 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6435 curproxy->check_req = (char *)malloc(curproxy->check_len);
6436 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006437 }
6438
Willy Tarreau193b8c62012-11-22 00:17:38 +01006439 /* ensure that cookie capture length is not too large */
6440 if (curproxy->capture_len >= global.tune.cookie_len) {
6441 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6442 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6443 err_code |= ERR_WARN;
6444 curproxy->capture_len = global.tune.cookie_len - 1;
6445 }
6446
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006447 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006448 if (curproxy->nb_req_cap) {
6449 if (curproxy->mode == PR_MODE_HTTP) {
6450 curproxy->req_cap_pool = create_pool("ptrcap",
6451 curproxy->nb_req_cap * sizeof(char *),
6452 MEM_F_SHARED);
6453 } else {
6454 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6455 proxy_type_str(curproxy), curproxy->id);
6456 err_code |= ERR_WARN;
6457 curproxy->to_log &= ~LW_REQHDR;
6458 curproxy->nb_req_cap = 0;
6459 }
6460 }
6461
6462 if (curproxy->nb_rsp_cap) {
6463 if (curproxy->mode == PR_MODE_HTTP) {
6464 curproxy->rsp_cap_pool = create_pool("ptrcap",
6465 curproxy->nb_rsp_cap * sizeof(char *),
6466 MEM_F_SHARED);
6467 } else {
6468 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6469 proxy_type_str(curproxy), curproxy->id);
6470 err_code |= ERR_WARN;
6471 curproxy->to_log &= ~LW_REQHDR;
6472 curproxy->nb_rsp_cap = 0;
6473 }
6474 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006475
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 /* first, we will invert the servers list order */
6477 newsrv = NULL;
6478 while (curproxy->srv) {
6479 struct server *next;
6480
6481 next = curproxy->srv->next;
6482 curproxy->srv->next = newsrv;
6483 newsrv = curproxy->srv;
6484 if (!next)
6485 break;
6486 curproxy->srv = next;
6487 }
6488
Willy Tarreau17edc812014-01-03 12:14:34 +01006489 /* Check that no server name conflicts. This causes trouble in the stats.
6490 * We only emit a warning for the first conflict affecting each server,
6491 * in order to avoid combinatory explosion if all servers have the same
6492 * name. We do that only for servers which do not have an explicit ID,
6493 * because these IDs were made also for distinguishing them and we don't
6494 * want to annoy people who correctly manage them.
6495 */
6496 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6497 struct server *other_srv;
6498
6499 if (newsrv->puid)
6500 continue;
6501
6502 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6503 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6504 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6505 newsrv->conf.file, newsrv->conf.line,
6506 proxy_type_str(curproxy), curproxy->id,
6507 newsrv->id, other_srv->conf.line);
6508 break;
6509 }
6510 }
6511 }
6512
Willy Tarreaudd701652010-05-25 23:03:02 +02006513 /* assign automatic UIDs to servers which don't have one yet */
6514 next_id = 1;
6515 newsrv = curproxy->srv;
6516 while (newsrv != NULL) {
6517 if (!newsrv->puid) {
6518 /* server ID not set, use automatic numbering with first
6519 * spare entry starting with next_svid.
6520 */
6521 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6522 newsrv->conf.id.key = newsrv->puid = next_id;
6523 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6524 }
6525 next_id++;
6526 newsrv = newsrv->next;
6527 }
6528
Willy Tarreau20697042007-11-15 23:26:18 +01006529 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006530 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531
Willy Tarreau62c3be22012-01-20 13:12:32 +01006532 /*
6533 * If this server supports a maxconn parameter, it needs a dedicated
6534 * tasks to fill the emptied slots when a connection leaves.
6535 * Also, resolve deferred tracking dependency if needed.
6536 */
6537 newsrv = curproxy->srv;
6538 while (newsrv != NULL) {
6539 if (newsrv->minconn > newsrv->maxconn) {
6540 /* Only 'minconn' was specified, or it was higher than or equal
6541 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6542 * this will avoid further useless expensive computations.
6543 */
6544 newsrv->maxconn = newsrv->minconn;
6545 } else if (newsrv->maxconn && !newsrv->minconn) {
6546 /* minconn was not specified, so we set it to maxconn */
6547 newsrv->minconn = newsrv->maxconn;
6548 }
6549
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006550#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006551 if (newsrv->use_ssl || newsrv->check.use_ssl)
6552 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006553#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006554
Willy Tarreau2f075e92013-12-03 11:11:34 +01006555 /* set the check type on the server */
6556 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6557
Willy Tarreau62c3be22012-01-20 13:12:32 +01006558 if (newsrv->trackit) {
6559 struct proxy *px;
6560 struct server *srv;
6561 char *pname, *sname;
6562
6563 pname = newsrv->trackit;
6564 sname = strrchr(pname, '/');
6565
6566 if (sname)
6567 *sname++ = '\0';
6568 else {
6569 sname = pname;
6570 pname = NULL;
6571 }
6572
6573 if (pname) {
6574 px = findproxy(pname, PR_CAP_BE);
6575 if (!px) {
6576 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6577 proxy_type_str(curproxy), curproxy->id,
6578 newsrv->id, pname);
6579 cfgerr++;
6580 goto next_srv;
6581 }
6582 } else
6583 px = curproxy;
6584
6585 srv = findserver(px, sname);
6586 if (!srv) {
6587 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6588 proxy_type_str(curproxy), curproxy->id,
6589 newsrv->id, sname);
6590 cfgerr++;
6591 goto next_srv;
6592 }
6593
Willy Tarreauff5ae352013-12-11 20:36:34 +01006594 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006595 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6596 "tracking as it does not have checks enabled.\n",
6597 proxy_type_str(curproxy), curproxy->id,
6598 newsrv->id, px->id, srv->id);
6599 cfgerr++;
6600 goto next_srv;
6601 }
6602
6603 if (curproxy != px &&
6604 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6605 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6606 "tracking: disable-on-404 option inconsistency.\n",
6607 proxy_type_str(curproxy), curproxy->id,
6608 newsrv->id, px->id, srv->id);
6609 cfgerr++;
6610 goto next_srv;
6611 }
6612
6613 /* if the other server is forced disabled, we have to do the same here */
6614 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006615 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006616 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006617 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006618 }
6619
6620 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006621 newsrv->tracknext = srv->trackers;
6622 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006623
6624 free(newsrv->trackit);
6625 newsrv->trackit = NULL;
6626 }
6627 next_srv:
6628 newsrv = newsrv->next;
6629 }
6630
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006631 /* We have to initialize the server lookup mechanism depending
6632 * on what LB algorithm was choosen.
6633 */
6634
6635 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6636 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6637 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006638 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6639 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6640 init_server_map(curproxy);
6641 } else {
6642 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6643 fwrr_init_server_groups(curproxy);
6644 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006645 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006646
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006647 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006648 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6649 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6650 fwlc_init_server_tree(curproxy);
6651 } else {
6652 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6653 fas_init_server_tree(curproxy);
6654 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006655 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006656
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006657 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006658 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6659 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6660 chash_init_server_tree(curproxy);
6661 } else {
6662 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6663 init_server_map(curproxy);
6664 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006665 break;
6666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667
6668 if (curproxy->options & PR_O_LOGASAP)
6669 curproxy->to_log &= ~LW_BYTES;
6670
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006671 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006672 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006673 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6674 proxy_type_str(curproxy), curproxy->id);
6675 err_code |= ERR_WARN;
6676 }
6677
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006678 if (curproxy->mode != PR_MODE_HTTP) {
6679 int optnum;
6680
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006681 if (curproxy->uri_auth) {
6682 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6683 proxy_type_str(curproxy), curproxy->id);
6684 err_code |= ERR_WARN;
6685 curproxy->uri_auth = NULL;
6686 }
6687
Willy Tarreau87cf5142011-08-19 22:57:24 +02006688 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006689 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6690 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6691 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006692 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006693 }
6694
6695 if (curproxy->options & PR_O_ORGTO) {
6696 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6697 "originalto", proxy_type_str(curproxy), curproxy->id);
6698 err_code |= ERR_WARN;
6699 curproxy->options &= ~PR_O_ORGTO;
6700 }
6701
6702 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6703 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6704 (curproxy->cap & cfg_opts[optnum].cap) &&
6705 (curproxy->options & cfg_opts[optnum].val)) {
6706 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6707 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6708 err_code |= ERR_WARN;
6709 curproxy->options &= ~cfg_opts[optnum].val;
6710 }
6711 }
6712
6713 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6714 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6715 (curproxy->cap & cfg_opts2[optnum].cap) &&
6716 (curproxy->options2 & cfg_opts2[optnum].val)) {
6717 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6718 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6719 err_code |= ERR_WARN;
6720 curproxy->options2 &= ~cfg_opts2[optnum].val;
6721 }
6722 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006723
Pieter Baauwd551fb52013-05-08 22:49:23 +02006724#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006725 if (curproxy->conn_src.bind_hdr_occ) {
6726 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006727 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006728 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006729 err_code |= ERR_WARN;
6730 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006731#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006732 }
6733
Willy Tarreaubaaee002006-06-26 02:48:02 +02006734 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006735 * ensure that we're not cross-dressing a TCP server into HTTP.
6736 */
6737 newsrv = curproxy->srv;
6738 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006739 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006740 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6741 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006742 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006743 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006744
Willy Tarreau0cec3312011-10-31 13:49:26 +01006745 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6746 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6747 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6748 err_code |= ERR_WARN;
6749 }
6750
Willy Tarreau82ffa392013-08-13 17:19:08 +02006751 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6752 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6753 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6754 err_code |= ERR_WARN;
6755 }
6756
Pieter Baauwd551fb52013-05-08 22:49:23 +02006757#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006758 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6759 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006760 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 +01006761 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006762 err_code |= ERR_WARN;
6763 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006764#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006765 newsrv = newsrv->next;
6766 }
6767
Willy Tarreauc1a21672009-08-16 22:37:44 +02006768 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006769 if (!curproxy->accept)
6770 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006771
Willy Tarreauc1a21672009-08-16 22:37:44 +02006772 if (curproxy->tcp_req.inspect_delay ||
6773 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006774 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006775
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006776 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006777 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006778 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006779 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006780
6781 /* both TCP and HTTP must check switching rules */
6782 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6783 }
6784
6785 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006786 if (curproxy->tcp_req.inspect_delay ||
6787 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6788 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6789
Emeric Brun97679e72010-09-23 17:56:44 +02006790 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6791 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6792
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006793 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006794 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006795 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006796 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006797
6798 /* If the backend does requires RDP cookie persistence, we have to
6799 * enable the corresponding analyser.
6800 */
6801 if (curproxy->options2 & PR_O2_RDPC_PRST)
6802 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6803 }
6804
Emeric Brunc52962f2012-11-15 18:28:02 +01006805#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006806 /* Configure SSL for each bind line.
6807 * Note: if configuration fails at some point, the ->ctx member
6808 * remains NULL so that listeners can later detach.
6809 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006810 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006811 int alloc_ctx;
6812
Emeric Brunc52962f2012-11-15 18:28:02 +01006813 if (!bind_conf->is_ssl) {
6814 if (bind_conf->default_ctx) {
6815 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6816 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6817 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006818 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006819 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006820 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006821 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006822 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006823 cfgerr++;
6824 continue;
6825 }
6826
Emeric Brun8dc60392014-05-09 13:52:00 +02006827 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006828 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006829 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6830 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");
6831 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006832 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006833 cfgerr++;
6834 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006835 }
6836
Emeric Brunfc0421f2012-09-07 17:30:07 +02006837 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006838 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006839 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006840#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006841
Willy Tarreaue6b98942007-10-29 01:09:36 +01006842 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006843 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006844 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006845 if (!listener->luid) {
6846 /* listener ID not set, use automatic numbering with first
6847 * spare entry starting with next_luid.
6848 */
6849 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6850 listener->conf.id.key = listener->luid = next_id;
6851 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006852 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006853 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006854
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006855 /* enable separate counters */
6856 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6857 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006858 if (!listener->name)
6859 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006860 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006861
Willy Tarreaue6b98942007-10-29 01:09:36 +01006862 if (curproxy->options & PR_O_TCP_NOLING)
6863 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006864 if (!listener->maxconn)
6865 listener->maxconn = curproxy->maxconn;
6866 if (!listener->backlog)
6867 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006868 if (!listener->maxaccept)
6869 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6870
6871 /* we want to have an optimal behaviour on single process mode to
6872 * maximize the work at once, but in multi-process we want to keep
6873 * some fairness between processes, so we target half of the max
6874 * number of events to be balanced over all the processes the proxy
6875 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6876 * used to disable the limit.
6877 */
6878 if (listener->maxaccept > 0) {
6879 if (nbproc > 1)
6880 listener->maxaccept = (listener->maxaccept + 1) / 2;
6881 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6882 }
6883
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006884 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006885 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006886 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006887 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006888
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006889 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6890 listener->options |= LI_O_TCP_RULES;
6891
Willy Tarreaude3041d2010-05-31 10:56:17 +02006892 if (curproxy->mon_mask.s_addr)
6893 listener->options |= LI_O_CHK_MONNET;
6894
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006895 /* smart accept mode is automatic in HTTP mode */
6896 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006897 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006898 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6899 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006900 }
6901
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006902 /* Release unused SSL configs */
6903 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6904 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006905 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006906#ifdef USE_OPENSSL
6907 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006908 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006909 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006910 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006911 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006912#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006913 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006914
Willy Tarreau102df612014-05-07 23:56:38 +02006915 if (nbproc > 1) {
6916 if (curproxy->uri_auth) {
6917 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6918 curproxy->id);
6919 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6920 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6921 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006922 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006923 }
Willy Tarreau102df612014-05-07 23:56:38 +02006924 if (curproxy->appsession_name) {
6925 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6926 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006927 }
Willy Tarreau102df612014-05-07 23:56:38 +02006928 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6929 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6930 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006931 }
6932 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006933
6934 /* create the task associated with the proxy */
6935 curproxy->task = task_new();
6936 if (curproxy->task) {
6937 curproxy->task->context = curproxy;
6938 curproxy->task->process = manage_proxy;
6939 /* no need to queue, it will be done automatically if some
6940 * listener gets limited.
6941 */
6942 curproxy->task->expire = TICK_ETERNITY;
6943 } else {
6944 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6945 curproxy->id);
6946 cfgerr++;
6947 }
6948
Willy Tarreaubaaee002006-06-26 02:48:02 +02006949 curproxy = curproxy->next;
6950 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006951
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006952 /* Check multi-process mode compatibility */
6953 if (global.nbproc > 1) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02006954 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
6955 unsigned long mask;
6956
6957 mask = nbits(global.nbproc);
6958 if (global.stats_fe->bind_proc)
6959 mask &= global.stats_fe->bind_proc;
6960
6961 if (bind_conf->bind_proc)
6962 mask &= bind_conf->bind_proc;
6963
6964 /* stop here if more than one process is used */
6965 if (popcount(mask) > 1)
6966 break;
6967 }
6968 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
6969 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 +01006970 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006971 }
6972
6973 /* automatically compute fullconn if not set. We must not do it in the
6974 * loop above because cross-references are not yet fully resolved.
6975 */
6976 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6977 /* If <fullconn> is not set, let's set it to 10% of the sum of
6978 * the possible incoming frontend's maxconns.
6979 */
6980 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6981 struct proxy *fe;
6982 int total = 0;
6983
6984 /* sum up the number of maxconns of frontends which
6985 * reference this backend at least once or which are
6986 * the same one ('listen').
6987 */
6988 for (fe = proxy; fe; fe = fe->next) {
6989 struct switching_rule *rule;
6990 struct hdr_exp *exp;
6991 int found = 0;
6992
6993 if (!(fe->cap & PR_CAP_FE))
6994 continue;
6995
6996 if (fe == curproxy) /* we're on a "listen" instance */
6997 found = 1;
6998
6999 if (fe->defbe.be == curproxy) /* "default_backend" */
7000 found = 1;
7001
7002 /* check if a "use_backend" rule matches */
7003 if (!found) {
7004 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007005 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007006 found = 1;
7007 break;
7008 }
7009 }
7010 }
7011
7012 /* check if a "reqsetbe" rule matches */
7013 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7014 if (exp->action == ACT_SETBE &&
7015 (struct proxy *)exp->replace == curproxy) {
7016 found = 1;
7017 break;
7018 }
7019 }
7020
7021 /* now we've checked all possible ways to reference a backend
7022 * from a frontend.
7023 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007024 if (!found)
7025 continue;
7026 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007027 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007028 /* we have the sum of the maxconns in <total>. We only
7029 * keep 10% of that sum to set the default fullconn, with
7030 * a hard minimum of 1 (to avoid a divide by zero).
7031 */
7032 curproxy->fullconn = (total + 9) / 10;
7033 if (!curproxy->fullconn)
7034 curproxy->fullconn = 1;
7035 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007036 }
7037
Willy Tarreau056f5682010-06-06 15:51:11 +02007038 /* initialize stick-tables on backend capable proxies. This must not
7039 * be done earlier because the data size may be discovered while parsing
7040 * other proxies.
7041 */
Godbach9703e662013-12-11 21:11:41 +08007042 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007043 if (curproxy->state == PR_STSTOPPED)
7044 continue;
7045
Godbach9703e662013-12-11 21:11:41 +08007046 if (!stktable_init(&curproxy->table)) {
7047 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7048 cfgerr++;
7049 }
7050 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007051
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007052 /*
7053 * Recount currently required checks.
7054 */
7055
7056 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7057 int optnum;
7058
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007059 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7060 if (curproxy->options & cfg_opts[optnum].val)
7061 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007062
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007063 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7064 if (curproxy->options2 & cfg_opts2[optnum].val)
7065 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007066 }
7067
Willy Tarreau122541c2011-09-07 21:24:49 +02007068 if (peers) {
7069 struct peers *curpeers = peers, **last;
7070 struct peer *p, *pb;
7071
7072 /* Remove all peers sections which don't have a valid listener.
7073 * This can happen when a peers section is never referenced and
7074 * does not contain a local peer.
7075 */
7076 last = &peers;
7077 while (*last) {
7078 curpeers = *last;
7079 if (curpeers->peers_fe) {
7080 last = &curpeers->next;
7081 continue;
7082 }
7083
7084 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7085 curpeers->id, localpeer);
7086
7087 p = curpeers->remote;
7088 while (p) {
7089 pb = p->next;
7090 free(p->id);
7091 free(p);
7092 p = pb;
7093 }
7094
7095 /* Destroy and unlink this curpeers section.
7096 * Note: curpeers is backed up into *last.
7097 */
7098 free(curpeers->id);
7099 curpeers = curpeers->next;
7100 free(*last);
7101 *last = curpeers;
7102 }
7103 }
7104
Willy Tarreau34eb6712011-10-24 18:15:04 +02007105 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007106 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007107 MEM_F_SHARED);
7108
Willy Tarreaubb925012009-07-23 13:36:36 +02007109 if (cfgerr > 0)
7110 err_code |= ERR_ALERT | ERR_FATAL;
7111 out:
7112 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007113}
7114
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007115/*
7116 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7117 * parsing sessions.
7118 */
7119void cfg_register_keywords(struct cfg_kw_list *kwl)
7120{
7121 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7122}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007124/*
7125 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7126 */
7127void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7128{
7129 LIST_DEL(&kwl->list);
7130 LIST_INIT(&kwl->list);
7131}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007132
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007133/* this function register new section in the haproxy configuration file.
7134 * <section_name> is the name of this new section and <section_parser>
7135 * is the called parser. If two section declaration have the same name,
7136 * only the first declared is used.
7137 */
7138int cfg_register_section(char *section_name,
7139 int (*section_parser)(const char *, int, char **, int))
7140{
7141 struct cfg_section *cs;
7142
7143 cs = calloc(1, sizeof(*cs));
7144 if (!cs) {
7145 Alert("register section '%s': out of memory.\n", section_name);
7146 return 0;
7147 }
7148
7149 cs->section_name = section_name;
7150 cs->section_parser = section_parser;
7151
7152 LIST_ADDQ(&sections, &cs->list);
7153
7154 return 1;
7155}
7156
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157/*
7158 * Local variables:
7159 * c-indent-level: 8
7160 * c-basic-offset: 8
7161 * End:
7162 */